pre version bump
This commit is contained in:
parent
ee73adae39
commit
8066c76dfd
22
package.json
Normal file
22
package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "sensortoy",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://gitlab.silvrtree.co.uk/martind2000/sensortoy.git"
|
||||
},
|
||||
"author": "Martin Donnelly <martind2000@gmail.com>",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^3.1.0",
|
||||
"gulp-cache": "^0.4.5",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-cssnano": "^2.1.2"
|
||||
}
|
||||
}
|
94
platforms/android/assets/www/css/progress.css
Normal file
94
platforms/android/assets/www/css/progress.css
Normal file
@ -0,0 +1,94 @@
|
||||
/* Progress Bar */
|
||||
.progress {
|
||||
position: relative;
|
||||
height: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
background-color: #acece6;
|
||||
border-radius: 2px;
|
||||
background-clip: padding-box;
|
||||
/* margin: 0.5rem 0 1rem 0; */
|
||||
overflow: hidden; }
|
||||
|
||||
.progress .determinate {
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #26a69a;
|
||||
transition: width .3s linear; }
|
||||
|
||||
.progress .indeterminate {
|
||||
background-color: #26a69a; }
|
||||
|
||||
.progress .indeterminate:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; }
|
||||
|
||||
.progress .indeterminate:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
-webkit-animation-delay: 1.15s;
|
||||
animation-delay: 1.15s; }
|
||||
|
||||
@-webkit-keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
}
|
||||
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
}
|
||||
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
}
|
195
platforms/android/assets/www/css/ripple.css
Normal file
195
platforms/android/assets/www/css/ripple.css
Normal file
@ -0,0 +1,195 @@
|
||||
|
||||
@-webkit-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-o-keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes uil-ripple {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
33% {
|
||||
width: 44%;
|
||||
height: 44%;
|
||||
margin: -22% 0 0 -22%;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
width: 88%;
|
||||
height: 88%;
|
||||
margin: -44% 0 0 -44%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.uil-ripple-css {
|
||||
background: none;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
.uil-ripple-css div {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
border-radius: 50%;
|
||||
border-width: 12px;
|
||||
border-style: solid;
|
||||
-ms-animation: uil-ripple 2s ease-out infinite;
|
||||
-moz-animation: uil-ripple 2s ease-out infinite;
|
||||
-webkit-animation: uil-ripple 2s ease-out infinite;
|
||||
-o-animation: uil-ripple 2s ease-out infinite;
|
||||
animation: uil-ripple 2s ease-out infinite;
|
||||
}
|
||||
.uil-ripple-css div:nth-of-type(1) {
|
||||
border-color: #afafb7;
|
||||
}
|
||||
.uil-ripple-css div:nth-of-type(2) {
|
||||
border-color: #5cffd6;
|
||||
-ms-animation-delay: 1s;
|
||||
-moz-animation-delay: 1s;
|
||||
-webkit-animation-delay: 1s;
|
||||
-o-animation-delay: 1s;
|
||||
animation-delay: 1s;
|
||||
}
|
Binary file not shown.
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-300.woff
Normal file
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-300.woff
Normal file
Binary file not shown.
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-400.woff
Normal file
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-400.woff
Normal file
Binary file not shown.
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-500.woff
Normal file
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-500.woff
Normal file
Binary file not shown.
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-700.woff
Normal file
BIN
platforms/android/assets/www/fonts/Ubuntu-normal-700.woff
Normal file
Binary file not shown.
Binary file not shown.
41
platforms/android/assets/www/fonts/fonts.css
Normal file
41
platforms/android/assets/www/fonts/fonts.css
Normal file
@ -0,0 +1,41 @@
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(Material_Icons-normal-400.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url(Ubuntu-normal-300.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(Ubuntu-normal-400.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: url(Ubuntu-normal-500.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url(Ubuntu-normal-700.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu Condensed';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(Ubuntu_Condensed-normal-400.woff) format('woff');
|
||||
}
|
144
platforms/android/assets/www/js/device/CC2650/cc2650_humidity.js
Normal file
144
platforms/android/assets/www/js/device/CC2650/cc2650_humidity.js
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
*
|
||||
* User: Martin Donnelly
|
||||
* Date: 2016-05-20
|
||||
* Time: 10:13
|
||||
*
|
||||
*/
|
||||
/* global CAPABILITY, inheritsFrom */
|
||||
/* global ble */
|
||||
/* jshint browser: true , devel: true*/
|
||||
|
||||
var CC2650_HUM = function(p) {
|
||||
'use strict';
|
||||
this.name = 'Humidity';
|
||||
this.deviceID = p.deviceID || null;
|
||||
this.target = p.target || null;
|
||||
|
||||
this.capabilityID = 'F000AA20-0451-4000-B000-000000000000';
|
||||
this.serviceDef = {
|
||||
service: 'F000AA20-0451-4000-B000-000000000000',
|
||||
data: 'F000AA21-0451-4000-B000-000000000000',
|
||||
notification: 'F0002902-0451-4000-B000-000000000000',
|
||||
configuration: 'F000AA22-0451-4000-B000-000000000000',
|
||||
period: 'F000AA23-0451-4000-B000-000000000000'
|
||||
|
||||
};
|
||||
this.data = {temp: [], humidity: []};
|
||||
this.$result = {temp: null, humidity: null};
|
||||
this.setFrame();
|
||||
|
||||
this.startService = function() {
|
||||
'use strict';
|
||||
if (this.deviceID !== null) {
|
||||
|
||||
console.log('Starting CC2650 Humidity Service on ', this.deviceID);
|
||||
console.log(this.serviceDef);
|
||||
this.insertFrame();
|
||||
|
||||
ble.startNotification(this.deviceID,
|
||||
this.serviceDef.service,
|
||||
this.serviceDef.data,
|
||||
this.onHumidityData.bind(this),
|
||||
this.onError);
|
||||
|
||||
//Turn on barometer
|
||||
var humidityConfig = new Uint8Array(1);
|
||||
humidityConfig[0] = 0x01;
|
||||
ble.write(this.deviceID,
|
||||
this.serviceDef.service,
|
||||
this.serviceDef.configuration,
|
||||
humidityConfig.buffer,
|
||||
function() { console.log('Started Humidity.'); },
|
||||
this.onError);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.onHumidityData = function(data) {
|
||||
var hStr;
|
||||
var tStr;
|
||||
// Console.log(data);
|
||||
var message;
|
||||
var raw = new Uint16Array(data);
|
||||
|
||||
//-- calculate temperature [°C]
|
||||
var temp = (raw[0] / 65536) * 165 - 40;
|
||||
|
||||
//-- calculate relative humidity [%RH]
|
||||
var hum = (raw[1] / 65536) * 100;
|
||||
|
||||
tStr = temp.toFixed(2) + '°C';
|
||||
hStr = hum.toFixed(2) + '%RH';
|
||||
|
||||
message = 'Temperature <br/>' + tStr + 'Humidity <br/>' + hStr;
|
||||
|
||||
this.data.temp = this.storeData(temp, this.data.temp);
|
||||
this.data.humidity = this.storeData(hum, this.data.humidity);
|
||||
|
||||
|
||||
this.$result.temp.text(tStr);
|
||||
this.$result.humidity.text(hStr);
|
||||
|
||||
this.state = message;
|
||||
|
||||
// Console.log('Barometer:', this.state);
|
||||
};
|
||||
|
||||
this.animateGraph = function() {
|
||||
this.simpleGraph(this.data.temp, 'temp');
|
||||
this.simpleGraph(this.data.humidity, 'humidity');
|
||||
};
|
||||
|
||||
|
||||
this.insertFrame = function() {
|
||||
|
||||
var self = this;
|
||||
var blankChart;
|
||||
|
||||
// Call the parent displayForm first...
|
||||
this.superClass_.insertFrame.call(self);
|
||||
|
||||
var temp = this.frameID + '-t';
|
||||
var humidity = this.frameID + '-h';
|
||||
var row = $('<div />', {class: 'mui-row'});
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-accent', text: 'Temp:'}).appendTo(row);
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-dark', id: temp}).appendTo(row);
|
||||
$('<div />',
|
||||
{
|
||||
class: 'mui-col-xs-3 mui--text-accent',
|
||||
text: 'Humidity:'
|
||||
}).appendTo(row);
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-dark', id: humidity}).appendTo(row);
|
||||
|
||||
this.$id.append(row);
|
||||
|
||||
var tabBody = $('<ul>',{class: 'mui-tabs__bar mui-tabs__bar--justified'});
|
||||
$('<li>',{class: 'mui--is-active tabOnWhite'}).append($('<a>',{text: 'Temperature','data-mui-toggle': 'tab', 'data-mui-controls': (temp + '-pane')})).appendTo(tabBody);
|
||||
$('<li>',{class: 'tabOnWhite'}).append($('<a>',{text: 'Humidity','data-mui-toggle': 'tab', 'data-mui-controls': (humidity + '-pane')})).appendTo(tabBody);
|
||||
this.$id.append(tabBody);
|
||||
|
||||
blankChart = this.generateBlankGraph('temp');
|
||||
|
||||
this.$id.append($('<div>',{class: 'mui-tabs__pane mui--is-active',id: (temp + '-pane')}).append(blankChart));
|
||||
|
||||
blankChart = this.generateBlankGraph('humidity');
|
||||
this.$id.append($('<div>',{class: 'mui-tabs__pane',id: (humidity + '-pane')}).append(blankChart));
|
||||
|
||||
this.$result.temp = $('#' + temp);
|
||||
this.$result.humidity = $('#' + humidity);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inheritsFrom(CC2650_HUM, CAPABILITY);
|
||||
|
||||
capabilityManager.register({id:'F000AA20-0451-4000-B000-000000000000', module:CC2650_HUM});
|
@ -0,0 +1,148 @@
|
||||
/**
|
||||
*
|
||||
* User: Martin Donnelly
|
||||
* Date: 2016-05-20
|
||||
* Time: 10:13
|
||||
*
|
||||
*/
|
||||
/* global CAPABILITY, inheritsFrom */
|
||||
/* global ble */
|
||||
/* jshint browser: true , devel: true*/
|
||||
|
||||
var CC2650_TMP = function(p) {
|
||||
'use strict';
|
||||
this.name = 'Thermopile';
|
||||
this.deviceID = p.deviceID || null;
|
||||
this.target = p.target || null;
|
||||
|
||||
this.capabilityID = 'F000AA00-0451-4000-B000-000000000000';
|
||||
this.serviceDef = {
|
||||
service: 'F000AA00-0451-4000-B000-000000000000',
|
||||
data: 'F000AA01-0451-4000-B000-000000000000',
|
||||
notification: 'F0002902-0451-4000-B000-000000000000',
|
||||
configuration: 'F000AA02-0451-4000-B000-000000000000',
|
||||
period: 'F000AA03-0451-4000-B000-000000000000'
|
||||
|
||||
};
|
||||
|
||||
this.data = {temp: [], ambient: []};
|
||||
this.$result = {temp: null, ambient: null};
|
||||
this.setFrame();
|
||||
|
||||
this.startService = function() {
|
||||
'use strict';
|
||||
if (this.deviceID !== null) {
|
||||
|
||||
console.log('Starting CC2650 Thermopile Service on ', this.deviceID);
|
||||
console.log(this.serviceDef);
|
||||
this.insertFrame();
|
||||
|
||||
ble.startNotification(this.deviceID,
|
||||
this.serviceDef.service,
|
||||
this.serviceDef.data,
|
||||
this.onThermData.bind(this),
|
||||
this.onError);
|
||||
|
||||
//Turn on thermopile
|
||||
var tmpConfig = new Uint8Array(1);
|
||||
tmpConfig[0] = 0x01;
|
||||
ble.write(this.deviceID,
|
||||
this.serviceDef.service,
|
||||
this.serviceDef.configuration,
|
||||
tmpConfig.buffer,
|
||||
function() { console.log('Started Thermopile.'); },
|
||||
this.onError);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.onThermData = function(data) {
|
||||
|
||||
var ambTemp;
|
||||
var objTemp;
|
||||
var scale_lsb = 0.03125;
|
||||
var raw = new Uint16Array(data);
|
||||
|
||||
var it = raw[0] >> 2;
|
||||
|
||||
objTemp = it * scale_lsb;
|
||||
|
||||
it = raw[1] >> 2;
|
||||
|
||||
ambTemp = it * scale_lsb;
|
||||
|
||||
var tStr = objTemp.toFixed(2) + '°C';
|
||||
var aStr = ambTemp.toFixed(2) + '°C';
|
||||
|
||||
this.state = ['Temp: ', tStr, ', Ambient:', aStr].join(' ');
|
||||
|
||||
this.data.temp = this.storeData(objTemp, this.data.temp);
|
||||
this.data.ambient = this.storeData(ambTemp, this.data.ambient);
|
||||
|
||||
|
||||
this.$result.temp.text(tStr);
|
||||
this.$result.ambient.text(aStr);
|
||||
|
||||
};
|
||||
|
||||
this.animateGraph = function() {
|
||||
this.simpleGraph(this.data.temp, 'temp');
|
||||
this.simpleGraph(this.data.ambient, 'ambient');
|
||||
};
|
||||
|
||||
|
||||
|
||||
this.insertFrame = function() {
|
||||
|
||||
var blankChart;
|
||||
var self = this;
|
||||
// Console.log('Overloading...');
|
||||
// Call the parent displayForm first...
|
||||
|
||||
this.superClass_.insertFrame.call(self);
|
||||
|
||||
var temp = this.frameID + '-t';
|
||||
var amb = this.frameID + '-a';
|
||||
var row = $('<div />', {class: 'mui-row'});
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-accent', text: 'Temp:'}).appendTo(row);
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-dark', id: temp}).appendTo(row);
|
||||
$('<div />',
|
||||
{
|
||||
class: 'mui-col-xs-3 mui--text-accent',
|
||||
text: 'Ambient:'
|
||||
}).appendTo(row);
|
||||
|
||||
$('<div />',
|
||||
{class: 'mui-col-xs-3 mui--text-dark', id: amb}).appendTo(row);
|
||||
|
||||
this.$id.append(row);
|
||||
|
||||
var tabBody = $('<ul>',{class: 'mui-tabs__bar mui-tabs__bar--justified'});
|
||||
$('<li>',{class: 'mui--is-active tabOnWhite'}).append($('<a>',{ text: 'Temperature','data-mui-toggle': 'tab', 'data-mui-controls': (temp + '-pane')})).appendTo(tabBody);
|
||||
$('<li>', {class: 'tabOnWhite'}).append($('<a>',{ text: 'Ambient','data-mui-toggle': 'tab', 'data-mui-controls': (amb + '-pane')})).appendTo(tabBody);
|
||||
|
||||
this.$id.append(tabBody);
|
||||
|
||||
blankChart = this.generateBlankGraph('temp');
|
||||
|
||||
this.$id.append($('<div>',{class: 'mui-tabs__pane mui--is-active',id: (temp + '-pane')}).append(blankChart));
|
||||
|
||||
blankChart = this.generateBlankGraph('ambient');
|
||||
|
||||
this.$id.append($('<div>',{class: 'mui-tabs__pane',id: (amb + '-pane')}).append(blankChart));
|
||||
|
||||
this.$result.temp = $('#' + temp);
|
||||
this.$result.ambient = $('#' + amb);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inheritsFrom(CC2650_TMP, CAPABILITY);
|
||||
|
||||
capabilityManager.register({id: 'F000AA00-0451-4000-B000-000000000000', module: CC2650_TMP});
|
69
platforms/android/assets/www/js/mandecoder.js
Normal file
69
platforms/android/assets/www/js/mandecoder.js
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
*
|
||||
* User: Martin Donnelly
|
||||
* Date: 2016-05-24
|
||||
* Time: 14:21
|
||||
*
|
||||
*/
|
||||
var MANUFACTUREDECODER = function() {
|
||||
'use strict';
|
||||
|
||||
this.getManID = function(data) {
|
||||
return ('0000' + ((data[1] << 8) | data[0]).toString(16)).slice(-4).toUpperCase();
|
||||
},
|
||||
this.decodeIbeacon = function(data) {
|
||||
|
||||
// Not decoding anything yet.
|
||||
// https://support.kontakt.io/hc/en-gb/articles/201492492-iBeacon-advertising-packet-structure
|
||||
var bin = data;
|
||||
var obj = { msg: '(iBeacon)'};
|
||||
// obj.manID = ('0000' + ((bin[1] << 8) | bin[0]).toString(16)).slice(-4);
|
||||
obj.manID = this.getManID(bin);
|
||||
var uuid = [];
|
||||
uuid.push(bin[4].toString(16) + bin[5].toString(16) + bin[6].toString(16) + bin[7].toString(16)) ;
|
||||
|
||||
uuid.push(bin[8].toString(16) + bin[9].toString(16)) ;
|
||||
uuid.push(bin[10].toString(16) + bin[11].toString(16)) ;
|
||||
uuid.push(bin[12].toString(16) + bin[13].toString(16)) ;
|
||||
|
||||
uuid.push(bin[14].toString(16) + bin[15].toString(16) + bin[16].toString(16) + bin[17].toString(16) + bin[18].toString(16) + bin[19].toString(16)) ;
|
||||
|
||||
obj.uuid = uuid.join('-');
|
||||
|
||||
|
||||
return obj;
|
||||
};
|
||||
this.decodeSiliconLabsSensorPuck = function(data) {
|
||||
var bin = data;
|
||||
var obj = {data:{}};
|
||||
//obj.manID = ('0000' + ((bin[1] << 8) | bin[0]).toString(16)).slice(-4);
|
||||
obj.manID = this.getManID(bin);
|
||||
obj.a = (bin[3] << 8) | bin[2];
|
||||
obj.b = (bin[5] << 8) | bin[4];
|
||||
obj.data.humidity = (bin[7] << 8) | bin[6];
|
||||
obj.data.temp = (bin[9] << 8) | bin[8];
|
||||
obj.c = (bin[11] << 8) | bin[10];
|
||||
obj.d = (bin[13] << 8) | bin[12];
|
||||
|
||||
obj.msg = 'Humidity: ' + (obj.data.humidity / 10) + ', temp: ' + (obj.data.temp / 10);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
this.decodeSansible = function(data) {
|
||||
var bin = data;
|
||||
var obj = {data:{}};
|
||||
// obj.manID = ('0000' + ((bin[1] << 8) | bin[0]).toString(16)).slice(-4);
|
||||
obj.manID = this.getManID(bin);
|
||||
|
||||
obj.data.p1 = ((bin[2] << 16) | bin[3] << 8 | bin[4]);
|
||||
obj.data.p2 = ((bin[5] << 16) | bin[6] << 8 | bin[7]);
|
||||
|
||||
obj.msg = 'Left: ' + (obj.data.p1 / 100) + ' hPa, Right: ' + (obj.data.p2 / 100) + ' hPa';
|
||||
return obj;
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
@ -53,9 +53,9 @@ var BATTERY = function() {
|
||||
this.onError);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inheritsFrom(BATTERY, CAPABILITY);
|
||||
capabilityManager.register({id: '180F', module: BATTERY});
|
||||
|
File diff suppressed because it is too large
Load Diff
15
platforms/android/assets/www/js/standards/gadget.js
Normal file
15
platforms/android/assets/www/js/standards/gadget.js
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
*
|
||||
* User: Martin Donnelly
|
||||
* Date: 2016-06-01
|
||||
* Time: 13:30
|
||||
*
|
||||
*/
|
||||
|
||||
var GADGET = function(p) {
|
||||
'use strict';
|
||||
|
||||
|
||||
this._gadget = p;
|
||||
|
||||
};
|
803
platforms/android/assets/www/libs/smoothie.js
Normal file
803
platforms/android/assets/www/libs/smoothie.js
Normal file
@ -0,0 +1,803 @@
|
||||
// MIT License:
|
||||
//
|
||||
// Copyright (c) 2010-2013, Joe Walnes
|
||||
// 2013-2014, Drew Noakes
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/**
|
||||
* Smoothie Charts - http://smoothiecharts.org/
|
||||
* (c) 2010-2013, Joe Walnes
|
||||
* 2013-2014, Drew Noakes
|
||||
*
|
||||
* v1.0: Main charting library, by Joe Walnes
|
||||
* v1.1: Auto scaling of axis, by Neil Dunn
|
||||
* v1.2: fps (frames per second) option, by Mathias Petterson
|
||||
* v1.3: Fix for divide by zero, by Paul Nikitochkin
|
||||
* v1.4: Set minimum, top-scale padding, remove timeseries, add optional timer to reset bounds, by Kelley Reynolds
|
||||
* v1.5: Set default frames per second to 50... smoother.
|
||||
* .start(), .stop() methods for conserving CPU, by Dmitry Vyal
|
||||
* options.interpolation = 'bezier' or 'line', by Dmitry Vyal
|
||||
* options.maxValue to fix scale, by Dmitry Vyal
|
||||
* v1.6: minValue/maxValue will always get converted to floats, by Przemek Matylla
|
||||
* v1.7: options.grid.fillStyle may be a transparent color, by Dmitry A. Shashkin
|
||||
* Smooth rescaling, by Kostas Michalopoulos
|
||||
* v1.8: Set max length to customize number of live points in the dataset with options.maxDataSetLength, by Krishna Narni
|
||||
* v1.9: Display timestamps along the bottom, by Nick and Stev-io
|
||||
* (https://groups.google.com/forum/?fromgroups#!topic/smoothie-charts/-Ywse8FCpKI%5B1-25%5D)
|
||||
* Refactored by Krishna Narni, to support timestamp formatting function
|
||||
* v1.10: Switch to requestAnimationFrame, removed the now obsoleted options.fps, by Gergely Imreh
|
||||
* v1.11: options.grid.sharpLines option added, by @drewnoakes
|
||||
* Addressed warning seen in Firefox when seriesOption.fillStyle undefined, by @drewnoakes
|
||||
* v1.12: Support for horizontalLines added, by @drewnoakes
|
||||
* Support for yRangeFunction callback added, by @drewnoakes
|
||||
* v1.13: Fixed typo (#32), by @alnikitich
|
||||
* v1.14: Timer cleared when last TimeSeries removed (#23), by @davidgaleano
|
||||
* Fixed diagonal line on chart at start/end of data stream, by @drewnoakes
|
||||
* v1.15: Support for npm package (#18), by @dominictarr
|
||||
* Fixed broken removeTimeSeries function (#24) by @davidgaleano
|
||||
* Minor performance and tidying, by @drewnoakes
|
||||
* v1.16: Bug fix introduced in v1.14 relating to timer creation/clearance (#23), by @drewnoakes
|
||||
* TimeSeries.append now deals with out-of-order timestamps, and can merge duplicates, by @zacwitte (#12)
|
||||
* Documentation and some local variable renaming for clarity, by @drewnoakes
|
||||
* v1.17: Allow control over font size (#10), by @drewnoakes
|
||||
* Timestamp text won't overlap, by @drewnoakes
|
||||
* v1.18: Allow control of max/min label precision, by @drewnoakes
|
||||
* Added 'borderVisible' chart option, by @drewnoakes
|
||||
* Allow drawing series with fill but no stroke (line), by @drewnoakes
|
||||
* v1.19: Avoid unnecessary repaints, and fixed flicker in old browsers having multiple charts in document (#40), by @asbai
|
||||
* v1.20: Add SmoothieChart.getTimeSeriesOptions and SmoothieChart.bringToFront functions, by @drewnoakes
|
||||
* v1.21: Add 'step' interpolation mode, by @drewnoakes
|
||||
* v1.22: Add support for different pixel ratios. Also add optional y limit formatters, by @copacetic
|
||||
* v1.23: Fix bug introduced in v1.22 (#44), by @drewnoakes
|
||||
* v1.24: Fix bug introduced in v1.23, re-adding parseFloat to y-axis formatter defaults, by @siggy_sf
|
||||
* v1.25: Fix bug seen when adding a data point to TimeSeries which is older than the current data, by @Nking92
|
||||
* Draw time labels on top of series, by @comolosabia
|
||||
* Add TimeSeries.clear function, by @drewnoakes
|
||||
* v1.26: Add support for resizing on high device pixel ratio screens, by @copacetic
|
||||
* v1.27: Fix bug introduced in v1.26 for non whole number devicePixelRatio values, by @zmbush
|
||||
* v1.28: Add 'minValueScale' option, by @megawac
|
||||
*/
|
||||
|
||||
;(function(exports) {
|
||||
|
||||
var Util = {
|
||||
extend: function() {
|
||||
arguments[0] = arguments[0] || {};
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
{
|
||||
for (var key in arguments[i])
|
||||
{
|
||||
if (arguments[i].hasOwnProperty(key))
|
||||
{
|
||||
if (typeof(arguments[i][key]) === 'object') {
|
||||
if (arguments[i][key] instanceof Array) {
|
||||
arguments[0][key] = arguments[i][key];
|
||||
} else {
|
||||
arguments[0][key] = Util.extend(arguments[0][key], arguments[i][key]);
|
||||
}
|
||||
} else {
|
||||
arguments[0][key] = arguments[i][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arguments[0];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialises a new <code>TimeSeries</code> with optional data options.
|
||||
*
|
||||
* Options are of the form (defaults shown):
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* resetBounds: true, // enables/disables automatic scaling of the y-axis
|
||||
* resetBoundsInterval: 3000 // the period between scaling calculations, in millis
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Presentation options for TimeSeries are specified as an argument to <code>SmoothieChart.addTimeSeries</code>.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function TimeSeries(options) {
|
||||
this.options = Util.extend({}, TimeSeries.defaultOptions, options);
|
||||
this.clear();
|
||||
}
|
||||
|
||||
TimeSeries.defaultOptions = {
|
||||
resetBoundsInterval: 3000,
|
||||
resetBounds: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears all data and state from this TimeSeries object.
|
||||
*/
|
||||
TimeSeries.prototype.clear = function() {
|
||||
this.data = [];
|
||||
this.maxValue = Number.NaN; // The maximum value ever seen in this TimeSeries.
|
||||
this.minValue = Number.NaN; // The minimum value ever seen in this TimeSeries.
|
||||
};
|
||||
|
||||
/**
|
||||
* Recalculate the min/max values for this <code>TimeSeries</code> object.
|
||||
*
|
||||
* This causes the graph to scale itself in the y-axis.
|
||||
*/
|
||||
TimeSeries.prototype.resetBounds = function() {
|
||||
if (this.data.length) {
|
||||
// Walk through all data points, finding the min/max value
|
||||
this.maxValue = this.data[0][1];
|
||||
this.minValue = this.data[0][1];
|
||||
for (var i = 1; i < this.data.length; i++) {
|
||||
var value = this.data[i][1];
|
||||
if (value > this.maxValue) {
|
||||
this.maxValue = value;
|
||||
}
|
||||
if (value < this.minValue) {
|
||||
this.minValue = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No data exists, so set min/max to NaN
|
||||
this.maxValue = Number.NaN;
|
||||
this.minValue = Number.NaN;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a new data point to the <code>TimeSeries</code>, preserving chronological order.
|
||||
*
|
||||
* @param timestamp the position, in time, of this data point
|
||||
* @param value the value of this data point
|
||||
* @param sumRepeatedTimeStampValues if <code>timestamp</code> has an exact match in the series, this flag controls
|
||||
* whether it is replaced, or the values summed (defaults to false.)
|
||||
*/
|
||||
TimeSeries.prototype.append = function(timestamp, value, sumRepeatedTimeStampValues) {
|
||||
// Rewind until we hit an older timestamp
|
||||
var i = this.data.length - 1;
|
||||
while (i >= 0 && this.data[i][0] > timestamp) {
|
||||
i--;
|
||||
}
|
||||
|
||||
if (i === -1) {
|
||||
// This new item is the oldest data
|
||||
this.data.splice(0, 0, [timestamp, value]);
|
||||
} else if (this.data.length > 0 && this.data[i][0] === timestamp) {
|
||||
// Update existing values in the array
|
||||
if (sumRepeatedTimeStampValues) {
|
||||
// Sum this value into the existing 'bucket'
|
||||
this.data[i][1] += value;
|
||||
value = this.data[i][1];
|
||||
} else {
|
||||
// Replace the previous value
|
||||
this.data[i][1] = value;
|
||||
}
|
||||
} else if (i < this.data.length - 1) {
|
||||
// Splice into the correct position to keep timestamps in order
|
||||
this.data.splice(i + 1, 0, [timestamp, value]);
|
||||
} else {
|
||||
// Add to the end of the array
|
||||
this.data.push([timestamp, value]);
|
||||
}
|
||||
|
||||
this.maxValue = isNaN(this.maxValue) ? value : Math.max(this.maxValue, value);
|
||||
this.minValue = isNaN(this.minValue) ? value : Math.min(this.minValue, value);
|
||||
};
|
||||
|
||||
TimeSeries.prototype.dropOldData = function(oldestValidTime, maxDataSetLength) {
|
||||
// We must always keep one expired data point as we need this to draw the
|
||||
// line that comes into the chart from the left, but any points prior to that can be removed.
|
||||
var removeCount = 0;
|
||||
while (this.data.length - removeCount >= maxDataSetLength && this.data[removeCount + 1][0] < oldestValidTime) {
|
||||
removeCount++;
|
||||
}
|
||||
if (removeCount !== 0) {
|
||||
this.data.splice(0, removeCount);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialises a new <code>SmoothieChart</code>.
|
||||
*
|
||||
* Options are optional, and should be of the form below. Just specify the values you
|
||||
* need and the rest will be given sensible defaults as shown:
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* minValue: undefined, // specify to clamp the lower y-axis to a given value
|
||||
* maxValue: undefined, // specify to clamp the upper y-axis to a given value
|
||||
* maxValueScale: 1, // allows proportional padding to be added above the chart. for 10% padding, specify 1.1.
|
||||
* minValueScale: 1, // allows proportional padding to be added below the chart. for 10% padding, specify 1.1.
|
||||
* yRangeFunction: undefined, // function({min: , max: }) { return {min: , max: }; }
|
||||
* scaleSmoothing: 0.125, // controls the rate at which y-value zoom animation occurs
|
||||
* millisPerPixel: 20, // sets the speed at which the chart pans by
|
||||
* enableDpiScaling: true, // support rendering at different DPI depending on the device
|
||||
* yMinFormatter: function(min, precision) { // callback function that formats the min y value label
|
||||
* return parseFloat(min).toFixed(precision);
|
||||
* },
|
||||
* yMaxFormatter: function(max, precision) { // callback function that formats the max y value label
|
||||
* return parseFloat(max).toFixed(precision);
|
||||
* },
|
||||
* maxDataSetLength: 2,
|
||||
* interpolation: 'bezier' // one of 'bezier', 'linear', or 'step'
|
||||
* timestampFormatter: null, // optional function to format time stamps for bottom of chart
|
||||
* // you may use SmoothieChart.timeFormatter, or your own: function(date) { return ''; }
|
||||
* scrollBackwards: false, // reverse the scroll direction of the chart
|
||||
* horizontalLines: [], // [ { value: 0, color: '#ffffff', lineWidth: 1 } ]
|
||||
* grid:
|
||||
* {
|
||||
* fillStyle: '#000000', // the background colour of the chart
|
||||
* lineWidth: 1, // the pixel width of grid lines
|
||||
* strokeStyle: '#777777', // colour of grid lines
|
||||
* millisPerLine: 1000, // distance between vertical grid lines
|
||||
* sharpLines: false, // controls whether grid lines are 1px sharp, or softened
|
||||
* verticalSections: 2, // number of vertical sections marked out by horizontal grid lines
|
||||
* borderVisible: true // whether the grid lines trace the border of the chart or not
|
||||
* },
|
||||
* labels
|
||||
* {
|
||||
* disabled: false, // enables/disables labels showing the min/max values
|
||||
* fillStyle: '#ffffff', // colour for text of labels,
|
||||
* fontSize: 15,
|
||||
* fontFamily: 'sans-serif',
|
||||
* precision: 2
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function SmoothieChart(options) {
|
||||
this.options = Util.extend({}, SmoothieChart.defaultChartOptions, options);
|
||||
this.seriesSet = [];
|
||||
this.currentValueRange = 1;
|
||||
this.currentVisMinValue = 0;
|
||||
this.lastRenderTimeMillis = 0;
|
||||
}
|
||||
|
||||
SmoothieChart.defaultChartOptions = {
|
||||
millisPerPixel: 20,
|
||||
enableDpiScaling: true,
|
||||
yMinFormatter: function(min, precision) {
|
||||
return parseFloat(min).toFixed(precision);
|
||||
},
|
||||
yMaxFormatter: function(max, precision) {
|
||||
return parseFloat(max).toFixed(precision);
|
||||
},
|
||||
maxValueScale: 1,
|
||||
minValueScale: 1,
|
||||
interpolation: 'bezier',
|
||||
scaleSmoothing: 0.125,
|
||||
maxDataSetLength: 2,
|
||||
scrollBackwards: false,
|
||||
grid: {
|
||||
fillStyle: '#000000',
|
||||
strokeStyle: '#777777',
|
||||
lineWidth: 1,
|
||||
sharpLines: false,
|
||||
millisPerLine: 1000,
|
||||
verticalSections: 2,
|
||||
borderVisible: true
|
||||
},
|
||||
labels: {
|
||||
fillStyle: '#ffffff',
|
||||
disabled: false,
|
||||
fontSize: 10,
|
||||
fontFamily: 'monospace',
|
||||
precision: 2
|
||||
},
|
||||
horizontalLines: []
|
||||
};
|
||||
|
||||
// Based on http://inspirit.github.com/jsfeat/js/compatibility.js
|
||||
SmoothieChart.AnimateCompatibility = (function() {
|
||||
var requestAnimationFrame = function(callback, element) {
|
||||
var requestAnimationFrame =
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(callback) {
|
||||
return window.setTimeout(function() {
|
||||
callback(new Date().getTime());
|
||||
}, 16);
|
||||
};
|
||||
return requestAnimationFrame.call(window, callback, element);
|
||||
},
|
||||
cancelAnimationFrame = function(id) {
|
||||
var cancelAnimationFrame =
|
||||
window.cancelAnimationFrame ||
|
||||
function(id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
return cancelAnimationFrame.call(window, id);
|
||||
};
|
||||
|
||||
return {
|
||||
requestAnimationFrame: requestAnimationFrame,
|
||||
cancelAnimationFrame: cancelAnimationFrame
|
||||
};
|
||||
})();
|
||||
|
||||
SmoothieChart.defaultSeriesPresentationOptions = {
|
||||
lineWidth: 1,
|
||||
strokeStyle: '#ffffff'
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a <code>TimeSeries</code> to this chart, with optional presentation options.
|
||||
*
|
||||
* Presentation options should be of the form (defaults shown):
|
||||
*
|
||||
* <pre>
|
||||
* {
|
||||
* lineWidth: 1,
|
||||
* strokeStyle: '#ffffff',
|
||||
* fillStyle: undefined
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
SmoothieChart.prototype.addTimeSeries = function(timeSeries, options) {
|
||||
this.seriesSet.push({timeSeries: timeSeries, options: Util.extend({}, SmoothieChart.defaultSeriesPresentationOptions, options)});
|
||||
if (timeSeries.options.resetBounds && timeSeries.options.resetBoundsInterval > 0) {
|
||||
timeSeries.resetBoundsTimerId = setInterval(
|
||||
function() {
|
||||
timeSeries.resetBounds();
|
||||
},
|
||||
timeSeries.options.resetBoundsInterval
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the specified <code>TimeSeries</code> from the chart.
|
||||
*/
|
||||
SmoothieChart.prototype.removeTimeSeries = function(timeSeries) {
|
||||
// Find the correct timeseries to remove, and remove it
|
||||
var numSeries = this.seriesSet.length;
|
||||
for (var i = 0; i < numSeries; i++) {
|
||||
if (this.seriesSet[i].timeSeries === timeSeries) {
|
||||
this.seriesSet.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If a timer was operating for that timeseries, remove it
|
||||
if (timeSeries.resetBoundsTimerId) {
|
||||
// Stop resetting the bounds, if we were
|
||||
clearInterval(timeSeries.resetBoundsTimerId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets render options for the specified <code>TimeSeries</code>.
|
||||
*
|
||||
* As you may use a single <code>TimeSeries</code> in multiple charts with different formatting in each usage,
|
||||
* these settings are stored in the chart.
|
||||
*/
|
||||
SmoothieChart.prototype.getTimeSeriesOptions = function(timeSeries) {
|
||||
// Find the correct timeseries to remove, and remove it
|
||||
var numSeries = this.seriesSet.length;
|
||||
for (var i = 0; i < numSeries; i++) {
|
||||
if (this.seriesSet[i].timeSeries === timeSeries) {
|
||||
return this.seriesSet[i].options;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Brings the specified <code>TimeSeries</code> to the top of the chart. It will be rendered last.
|
||||
*/
|
||||
SmoothieChart.prototype.bringToFront = function(timeSeries) {
|
||||
// Find the correct timeseries to remove, and remove it
|
||||
var numSeries = this.seriesSet.length;
|
||||
for (var i = 0; i < numSeries; i++) {
|
||||
if (this.seriesSet[i].timeSeries === timeSeries) {
|
||||
var set = this.seriesSet.splice(i, 1);
|
||||
this.seriesSet.push(set[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Instructs the <code>SmoothieChart</code> to start rendering to the provided canvas, with specified delay.
|
||||
*
|
||||
* @param canvas the target canvas element
|
||||
* @param delayMillis an amount of time to wait before a data point is shown. This can prevent the end of the series
|
||||
* from appearing on screen, with new values flashing into view, at the expense of some latency.
|
||||
*/
|
||||
SmoothieChart.prototype.streamTo = function(canvas, delayMillis) {
|
||||
this.canvas = canvas;
|
||||
this.delay = delayMillis;
|
||||
this.start();
|
||||
};
|
||||
|
||||
/**
|
||||
* Make sure the canvas has the optimal resolution for the device's pixel ratio.
|
||||
*/
|
||||
SmoothieChart.prototype.resize = function() {
|
||||
// TODO this function doesn't handle the value of enableDpiScaling changing during execution
|
||||
if (!this.options.enableDpiScaling || !window || window.devicePixelRatio === 1)
|
||||
return;
|
||||
|
||||
var dpr = window.devicePixelRatio;
|
||||
var width = parseInt(this.canvas.getAttribute('width'));
|
||||
var height = parseInt(this.canvas.getAttribute('height'));
|
||||
|
||||
if (!this.originalWidth || (Math.floor(this.originalWidth * dpr) !== width)) {
|
||||
this.originalWidth = width;
|
||||
this.canvas.setAttribute('width', (Math.floor(width * dpr)).toString());
|
||||
this.canvas.style.width = width + 'px';
|
||||
this.canvas.getContext('2d').scale(dpr, dpr);
|
||||
}
|
||||
|
||||
if (!this.originalHeight || (Math.floor(this.originalHeight * dpr) !== height)) {
|
||||
this.originalHeight = height;
|
||||
this.canvas.setAttribute('height', (Math.floor(height * dpr)).toString());
|
||||
this.canvas.style.height = height + 'px';
|
||||
this.canvas.getContext('2d').scale(dpr, dpr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the animation of this chart.
|
||||
*/
|
||||
SmoothieChart.prototype.start = function() {
|
||||
if (this.frame) {
|
||||
// We're already running, so just return
|
||||
return;
|
||||
}
|
||||
|
||||
// Renders a frame, and queues the next frame for later rendering
|
||||
var animate = function() {
|
||||
this.frame = SmoothieChart.AnimateCompatibility.requestAnimationFrame(function() {
|
||||
this.render();
|
||||
animate();
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
animate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops the animation of this chart.
|
||||
*/
|
||||
SmoothieChart.prototype.stop = function() {
|
||||
if (this.frame) {
|
||||
SmoothieChart.AnimateCompatibility.cancelAnimationFrame(this.frame);
|
||||
delete this.frame;
|
||||
}
|
||||
};
|
||||
|
||||
SmoothieChart.prototype.updateValueRange = function() {
|
||||
// Calculate the current scale of the chart, from all time series.
|
||||
var chartOptions = this.options,
|
||||
chartMaxValue = Number.NaN,
|
||||
chartMinValue = Number.NaN;
|
||||
|
||||
for (var d = 0; d < this.seriesSet.length; d++) {
|
||||
// TODO(ndunn): We could calculate / track these values as they stream in.
|
||||
var timeSeries = this.seriesSet[d].timeSeries;
|
||||
if (!isNaN(timeSeries.maxValue)) {
|
||||
chartMaxValue = !isNaN(chartMaxValue) ? Math.max(chartMaxValue, timeSeries.maxValue) : timeSeries.maxValue;
|
||||
}
|
||||
|
||||
if (!isNaN(timeSeries.minValue)) {
|
||||
chartMinValue = !isNaN(chartMinValue) ? Math.min(chartMinValue, timeSeries.minValue) : timeSeries.minValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale the chartMaxValue to add padding at the top if required
|
||||
if (chartOptions.maxValue != null) {
|
||||
chartMaxValue = chartOptions.maxValue;
|
||||
} else {
|
||||
chartMaxValue *= chartOptions.maxValueScale;
|
||||
}
|
||||
|
||||
// Set the minimum if we've specified one
|
||||
if (chartOptions.minValue != null) {
|
||||
chartMinValue = chartOptions.minValue;
|
||||
} else {
|
||||
chartMinValue -= Math.abs(chartMinValue * chartOptions.minValueScale - chartMinValue);
|
||||
}
|
||||
|
||||
// If a custom range function is set, call it
|
||||
if (this.options.yRangeFunction) {
|
||||
var range = this.options.yRangeFunction({min: chartMinValue, max: chartMaxValue});
|
||||
chartMinValue = range.min;
|
||||
chartMaxValue = range.max;
|
||||
}
|
||||
|
||||
if (!isNaN(chartMaxValue) && !isNaN(chartMinValue)) {
|
||||
var targetValueRange = chartMaxValue - chartMinValue;
|
||||
var valueRangeDiff = (targetValueRange - this.currentValueRange);
|
||||
var minValueDiff = (chartMinValue - this.currentVisMinValue);
|
||||
this.isAnimatingScale = Math.abs(valueRangeDiff) > 0.1 || Math.abs(minValueDiff) > 0.1;
|
||||
this.currentValueRange += chartOptions.scaleSmoothing * valueRangeDiff;
|
||||
this.currentVisMinValue += chartOptions.scaleSmoothing * minValueDiff;
|
||||
}
|
||||
|
||||
this.valueRange = { min: chartMinValue, max: chartMaxValue };
|
||||
};
|
||||
|
||||
SmoothieChart.prototype.render = function(canvas, time) {
|
||||
var nowMillis = new Date().getTime();
|
||||
|
||||
if (!this.isAnimatingScale) {
|
||||
// We're not animating. We can use the last render time and the scroll speed to work out whether
|
||||
// we actually need to paint anything yet. If not, we can return immediately.
|
||||
|
||||
// Render at least every 1/6th of a second. The canvas may be resized, which there is
|
||||
// no reliable way to detect.
|
||||
var maxIdleMillis = Math.min(1000/6, this.options.millisPerPixel);
|
||||
|
||||
if (nowMillis - this.lastRenderTimeMillis < maxIdleMillis) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.resize();
|
||||
|
||||
this.lastRenderTimeMillis = nowMillis;
|
||||
|
||||
canvas = canvas || this.canvas;
|
||||
time = time || nowMillis - (this.delay || 0);
|
||||
|
||||
// Round time down to pixel granularity, so motion appears smoother.
|
||||
time -= time % this.options.millisPerPixel;
|
||||
|
||||
var context = canvas.getContext('2d'),
|
||||
chartOptions = this.options,
|
||||
dimensions = { top: 0, left: 0, width: canvas.clientWidth, height: canvas.clientHeight },
|
||||
// Calculate the threshold time for the oldest data points.
|
||||
oldestValidTime = time - (dimensions.width * chartOptions.millisPerPixel),
|
||||
valueToYPixel = function(value) {
|
||||
var offset = value - this.currentVisMinValue;
|
||||
return this.currentValueRange === 0
|
||||
? dimensions.height
|
||||
: dimensions.height - (Math.round((offset / this.currentValueRange) * dimensions.height));
|
||||
}.bind(this),
|
||||
timeToXPixel = function(t) {
|
||||
if(chartOptions.scrollBackwards) {
|
||||
return Math.round((time - t) / chartOptions.millisPerPixel);
|
||||
}
|
||||
return Math.round(dimensions.width - ((time - t) / chartOptions.millisPerPixel));
|
||||
};
|
||||
|
||||
this.updateValueRange();
|
||||
|
||||
context.font = chartOptions.labels.fontSize + 'px ' + chartOptions.labels.fontFamily;
|
||||
|
||||
// Save the state of the canvas context, any transformations applied in this method
|
||||
// will get removed from the stack at the end of this method when .restore() is called.
|
||||
context.save();
|
||||
|
||||
// Move the origin.
|
||||
context.translate(dimensions.left, dimensions.top);
|
||||
|
||||
// Create a clipped rectangle - anything we draw will be constrained to this rectangle.
|
||||
// This prevents the occasional pixels from curves near the edges overrunning and creating
|
||||
// screen cheese (that phrase should need no explanation).
|
||||
context.beginPath();
|
||||
context.rect(0, 0, dimensions.width, dimensions.height);
|
||||
context.clip();
|
||||
|
||||
// Clear the working area.
|
||||
context.save();
|
||||
context.fillStyle = chartOptions.grid.fillStyle;
|
||||
context.clearRect(0, 0, dimensions.width, dimensions.height);
|
||||
context.fillRect(0, 0, dimensions.width, dimensions.height);
|
||||
context.restore();
|
||||
|
||||
// Grid lines...
|
||||
context.save();
|
||||
context.lineWidth = chartOptions.grid.lineWidth;
|
||||
context.strokeStyle = chartOptions.grid.strokeStyle;
|
||||
// Vertical (time) dividers.
|
||||
if (chartOptions.grid.millisPerLine > 0) {
|
||||
context.beginPath();
|
||||
for (var t = time - (time % chartOptions.grid.millisPerLine);
|
||||
t >= oldestValidTime;
|
||||
t -= chartOptions.grid.millisPerLine) {
|
||||
var gx = timeToXPixel(t);
|
||||
if (chartOptions.grid.sharpLines) {
|
||||
gx -= 0.5;
|
||||
}
|
||||
context.moveTo(gx, 0);
|
||||
context.lineTo(gx, dimensions.height);
|
||||
}
|
||||
context.stroke();
|
||||
context.closePath();
|
||||
}
|
||||
|
||||
// Horizontal (value) dividers.
|
||||
for (var v = 1; v < chartOptions.grid.verticalSections; v++) {
|
||||
var gy = Math.round(v * dimensions.height / chartOptions.grid.verticalSections);
|
||||
if (chartOptions.grid.sharpLines) {
|
||||
gy -= 0.5;
|
||||
}
|
||||
context.beginPath();
|
||||
context.moveTo(0, gy);
|
||||
context.lineTo(dimensions.width, gy);
|
||||
context.stroke();
|
||||
context.closePath();
|
||||
}
|
||||
// Bounding rectangle.
|
||||
if (chartOptions.grid.borderVisible) {
|
||||
context.beginPath();
|
||||
context.strokeRect(0, 0, dimensions.width, dimensions.height);
|
||||
context.closePath();
|
||||
}
|
||||
context.restore();
|
||||
|
||||
// Draw any horizontal lines...
|
||||
if (chartOptions.horizontalLines && chartOptions.horizontalLines.length) {
|
||||
for (var hl = 0; hl < chartOptions.horizontalLines.length; hl++) {
|
||||
var line = chartOptions.horizontalLines[hl],
|
||||
hly = Math.round(valueToYPixel(line.value)) - 0.5;
|
||||
context.strokeStyle = line.color || '#ffffff';
|
||||
context.lineWidth = line.lineWidth || 1;
|
||||
context.beginPath();
|
||||
context.moveTo(0, hly);
|
||||
context.lineTo(dimensions.width, hly);
|
||||
context.stroke();
|
||||
context.closePath();
|
||||
}
|
||||
}
|
||||
|
||||
// For each data set...
|
||||
for (var d = 0; d < this.seriesSet.length; d++) {
|
||||
context.save();
|
||||
var timeSeries = this.seriesSet[d].timeSeries,
|
||||
dataSet = timeSeries.data,
|
||||
seriesOptions = this.seriesSet[d].options;
|
||||
|
||||
// Delete old data that's moved off the left of the chart.
|
||||
timeSeries.dropOldData(oldestValidTime, chartOptions.maxDataSetLength);
|
||||
|
||||
// Set style for this dataSet.
|
||||
context.lineWidth = seriesOptions.lineWidth;
|
||||
context.strokeStyle = seriesOptions.strokeStyle;
|
||||
// Draw the line...
|
||||
context.beginPath();
|
||||
// Retain lastX, lastY for calculating the control points of bezier curves.
|
||||
var firstX = 0, lastX = 0, lastY = 0;
|
||||
for (var i = 0; i < dataSet.length && dataSet.length !== 1; i++) {
|
||||
var x = timeToXPixel(dataSet[i][0]),
|
||||
y = valueToYPixel(dataSet[i][1]);
|
||||
|
||||
if (i === 0) {
|
||||
firstX = x;
|
||||
context.moveTo(x, y);
|
||||
} else {
|
||||
switch (chartOptions.interpolation) {
|
||||
case "linear":
|
||||
case "line": {
|
||||
context.lineTo(x,y);
|
||||
break;
|
||||
}
|
||||
case "bezier":
|
||||
default: {
|
||||
// Great explanation of Bezier curves: http://en.wikipedia.org/wiki/Bezier_curve#Quadratic_curves
|
||||
//
|
||||
// Assuming A was the last point in the line plotted and B is the new point,
|
||||
// we draw a curve with control points P and Q as below.
|
||||
//
|
||||
// A---P
|
||||
// |
|
||||
// |
|
||||
// |
|
||||
// Q---B
|
||||
//
|
||||
// Importantly, A and P are at the same y coordinate, as are B and Q. This is
|
||||
// so adjacent curves appear to flow as one.
|
||||
//
|
||||
context.bezierCurveTo( // startPoint (A) is implicit from last iteration of loop
|
||||
Math.round((lastX + x) / 2), lastY, // controlPoint1 (P)
|
||||
Math.round((lastX + x)) / 2, y, // controlPoint2 (Q)
|
||||
x, y); // endPoint (B)
|
||||
break;
|
||||
}
|
||||
case "step": {
|
||||
context.lineTo(x,lastY);
|
||||
context.lineTo(x,y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastX = x; lastY = y;
|
||||
}
|
||||
|
||||
if (dataSet.length > 1) {
|
||||
if (seriesOptions.fillStyle) {
|
||||
// Close up the fill region.
|
||||
context.lineTo(dimensions.width + seriesOptions.lineWidth + 1, lastY);
|
||||
context.lineTo(dimensions.width + seriesOptions.lineWidth + 1, dimensions.height + seriesOptions.lineWidth + 1);
|
||||
context.lineTo(firstX, dimensions.height + seriesOptions.lineWidth);
|
||||
context.fillStyle = seriesOptions.fillStyle;
|
||||
context.fill();
|
||||
}
|
||||
|
||||
if (seriesOptions.strokeStyle && seriesOptions.strokeStyle !== 'none') {
|
||||
context.stroke();
|
||||
}
|
||||
context.closePath();
|
||||
}
|
||||
context.restore();
|
||||
}
|
||||
|
||||
// Draw the axis values on the chart.
|
||||
if (!chartOptions.labels.disabled && !isNaN(this.valueRange.min) && !isNaN(this.valueRange.max)) {
|
||||
var maxValueString = chartOptions.yMaxFormatter(this.valueRange.max, chartOptions.labels.precision),
|
||||
minValueString = chartOptions.yMinFormatter(this.valueRange.min, chartOptions.labels.precision),
|
||||
labelPos = chartOptions.scrollBackwards ? 0 : dimensions.width - context.measureText(maxValueString).width - 2;
|
||||
context.fillStyle = chartOptions.labels.fillStyle;
|
||||
context.fillText(maxValueString, labelPos, chartOptions.labels.fontSize);
|
||||
context.fillText(minValueString, labelPos, dimensions.height - 2);
|
||||
}
|
||||
|
||||
// Display timestamps along x-axis at the bottom of the chart.
|
||||
if (chartOptions.timestampFormatter && chartOptions.grid.millisPerLine > 0) {
|
||||
var textUntilX = chartOptions.scrollBackwards
|
||||
? context.measureText(minValueString).width
|
||||
: dimensions.width - context.measureText(minValueString).width + 4;
|
||||
for (var t = time - (time % chartOptions.grid.millisPerLine);
|
||||
t >= oldestValidTime;
|
||||
t -= chartOptions.grid.millisPerLine) {
|
||||
var gx = timeToXPixel(t);
|
||||
// Only draw the timestamp if it won't overlap with the previously drawn one.
|
||||
if ((!chartOptions.scrollBackwards && gx < textUntilX) || (chartOptions.scrollBackwards && gx > textUntilX)) {
|
||||
// Formats the timestamp based on user specified formatting function
|
||||
// SmoothieChart.timeFormatter function above is one such formatting option
|
||||
var tx = new Date(t),
|
||||
ts = chartOptions.timestampFormatter(tx),
|
||||
tsWidth = context.measureText(ts).width;
|
||||
|
||||
textUntilX = chartOptions.scrollBackwards
|
||||
? gx + tsWidth + 2
|
||||
: gx - tsWidth - 2;
|
||||
|
||||
context.fillStyle = chartOptions.labels.fillStyle;
|
||||
if(chartOptions.scrollBackwards) {
|
||||
context.fillText(ts, gx, dimensions.height - 2);
|
||||
} else {
|
||||
context.fillText(ts, gx - tsWidth, dimensions.height - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.restore(); // See .save() above.
|
||||
};
|
||||
|
||||
// Sample timestamp formatting function
|
||||
SmoothieChart.timeFormatter = function(date) {
|
||||
function pad2(number) { return (number < 10 ? '0' : '') + number }
|
||||
return pad2(date.getHours()) + ':' + pad2(date.getMinutes()) + ':' + pad2(date.getSeconds());
|
||||
};
|
||||
|
||||
exports.TimeSeries = TimeSeries;
|
||||
exports.SmoothieChart = SmoothieChart;
|
||||
|
||||
})(typeof exports === 'undefined' ? this : exports);
|
120
platforms/android/assets/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
120
platforms/android/assets/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileError = require('./FileError'),
|
||||
DirectoryReader = require('./DirectoryReader');
|
||||
|
||||
/**
|
||||
* An interface representing a directory on the file system.
|
||||
*
|
||||
* {boolean} isFile always false (readonly)
|
||||
* {boolean} isDirectory always true (readonly)
|
||||
* {DOMString} name of the directory, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the directory (readonly)
|
||||
* {FileSystem} filesystem on which the directory resides (readonly)
|
||||
*/
|
||||
var DirectoryEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
|
||||
// add trailing slash if it is missing
|
||||
if ((fullPath) && !/\/$/.test(fullPath)) {
|
||||
fullPath += "/";
|
||||
}
|
||||
// add trailing slash if it is missing
|
||||
if (nativeURL && !/\/$/.test(nativeURL)) {
|
||||
nativeURL += "/";
|
||||
}
|
||||
DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
|
||||
};
|
||||
|
||||
utils.extend(DirectoryEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new DirectoryReader to read entries from this directory
|
||||
*/
|
||||
DirectoryEntry.prototype.createReader = function() {
|
||||
return new DirectoryReader(this.toInternalURL());
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a directory
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
|
||||
* @param {Flags} options to create or exclusively create the directory
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getDirectory", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a directory and all of it's contents
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "removeRecursively", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a file
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
|
||||
* @param {Flags} options to create or exclusively create the file
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var FileEntry = require('./FileEntry');
|
||||
var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFile", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryEntry;
|
||||
|
||||
});
|
76
platforms/android/assets/www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
76
platforms/android/assets/www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError') ;
|
||||
|
||||
/**
|
||||
* An interface that lists the files and directories in a directory.
|
||||
*/
|
||||
function DirectoryReader(localURL) {
|
||||
this.localURL = localURL || null;
|
||||
this.hasReadEntries = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of entries from a directory.
|
||||
*
|
||||
* @param {Function} successCallback is called with a list of entries
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
|
||||
// If we've already read and passed on this directory's entries, return an empty list.
|
||||
if (this.hasReadEntries) {
|
||||
successCallback([]);
|
||||
return;
|
||||
}
|
||||
var reader = this;
|
||||
var win = typeof successCallback !== 'function' ? null : function(result) {
|
||||
var retVal = [];
|
||||
for (var i=0; i<result.length; i++) {
|
||||
var entry = null;
|
||||
if (result[i].isDirectory) {
|
||||
entry = new (require('./DirectoryEntry'))();
|
||||
}
|
||||
else if (result[i].isFile) {
|
||||
entry = new (require('./FileEntry'))();
|
||||
}
|
||||
entry.isDirectory = result[i].isDirectory;
|
||||
entry.isFile = result[i].isFile;
|
||||
entry.name = result[i].name;
|
||||
entry.fullPath = result[i].fullPath;
|
||||
entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
|
||||
entry.nativeURL = result[i].nativeURL;
|
||||
retVal.push(entry);
|
||||
}
|
||||
reader.hasReadEntries = true;
|
||||
successCallback(retVal);
|
||||
};
|
||||
var fail = typeof errorCallback !== 'function' ? null : function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "readEntries", [this.localURL]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryReader;
|
||||
|
||||
});
|
265
platforms/android/assets/www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
265
platforms/android/assets/www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
Metadata = require('./Metadata');
|
||||
|
||||
/**
|
||||
* Represents a file or directory on the local file system.
|
||||
*
|
||||
* @param isFile
|
||||
* {boolean} true if Entry is a file (readonly)
|
||||
* @param isDirectory
|
||||
* {boolean} true if Entry is a directory (readonly)
|
||||
* @param name
|
||||
* {DOMString} name of the file or directory, excluding the path
|
||||
* leading to it (readonly)
|
||||
* @param fullPath
|
||||
* {DOMString} the absolute full path to the file or directory
|
||||
* (readonly)
|
||||
* @param fileSystem
|
||||
* {FileSystem} the filesystem on which this entry resides
|
||||
* (readonly)
|
||||
* @param nativeURL
|
||||
* {DOMString} an alternate URL which can be used by native
|
||||
* webview controls, for example media players.
|
||||
* (optional, readonly)
|
||||
*/
|
||||
function Entry(isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
|
||||
this.isFile = !!isFile;
|
||||
this.isDirectory = !!isDirectory;
|
||||
this.name = name || '';
|
||||
this.fullPath = fullPath || '';
|
||||
this.filesystem = fileSystem || null;
|
||||
this.nativeURL = nativeURL || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
*/
|
||||
Entry.prototype.getMetadata = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
|
||||
var success = successCallback && function(entryMetadata) {
|
||||
var metadata = new Metadata({
|
||||
size: entryMetadata.size,
|
||||
modificationTime: entryMetadata.lastModifiedDate
|
||||
});
|
||||
successCallback(metadata);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(success, fail, "File", "getFileMetadata", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
* @param metadataObject
|
||||
* {Object} keys and values to set
|
||||
*/
|
||||
Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
|
||||
argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
|
||||
exec(successCallback, errorCallback, "File", "setMetadata", [this.toInternalURL(), metadataObject]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a file or directory to a new location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to move this entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new DirectoryEntry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "moveTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a directory to a different location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to copy the entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new Entry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
// success callback
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "copyTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be passed across the bridge to identify this entry.
|
||||
*/
|
||||
Entry.prototype.toInternalURL = function() {
|
||||
if (this.filesystem && this.filesystem.__format__) {
|
||||
return this.filesystem.__format__(this.fullPath, this.nativeURL);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be used to identify this entry.
|
||||
* Use a URL that can be used to as the src attribute of a <video> or
|
||||
* <audio> tag. If that is not possible, construct a cdvfile:// URL.
|
||||
*/
|
||||
Entry.prototype.toURL = function() {
|
||||
if (this.nativeURL) {
|
||||
return this.nativeURL;
|
||||
}
|
||||
// fullPath attribute may contain the full URL in the case that
|
||||
// toInternalURL fails.
|
||||
return this.toInternalURL() || "file://localhost" + this.fullPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
|
||||
* cdvfile:// URL, and this method was necessary to obtain URLs usable by the
|
||||
* webview.
|
||||
* See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
|
||||
* and CB-6300.
|
||||
*/
|
||||
Entry.prototype.toNativeURL = function() {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a URI that can be used to identify this entry.
|
||||
*
|
||||
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
|
||||
* @return uri
|
||||
*/
|
||||
Entry.prototype.toURI = function(mimeType) {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a file or directory. It is an error to attempt to delete a
|
||||
* directory that is not empty. It is an error to attempt to delete a
|
||||
* root directory of a file system.
|
||||
*
|
||||
* @param successCallback {Function} called with no parameters
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.remove = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.remove', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "remove", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Look up the parent DirectoryEntry of this entry.
|
||||
*
|
||||
* @param successCallback {Function} called with the parent DirectoryEntry object
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.getParent = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getParent', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getParent", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
module.exports = Entry;
|
||||
|
||||
});
|
82
platforms/android/assets/www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
82
platforms/android/assets/www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
cordova.define("cordova-plugin-file.File", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* name {DOMString} name of the file, without path information
|
||||
* fullPath {DOMString} the full path of the file, including the name
|
||||
* type {DOMString} mime type
|
||||
* lastModifiedDate {Date} last modified date
|
||||
* size {Number} size of the file in bytes
|
||||
*/
|
||||
|
||||
var File = function(name, localURL, type, lastModifiedDate, size){
|
||||
this.name = name || '';
|
||||
this.localURL = localURL || null;
|
||||
this.type = type || null;
|
||||
this.lastModified = lastModifiedDate || null;
|
||||
// For backwards compatibility, store the timestamp in lastModifiedDate as well
|
||||
this.lastModifiedDate = lastModifiedDate || null;
|
||||
this.size = size || 0;
|
||||
|
||||
// These store the absolute start and end for slicing the file.
|
||||
this.start = 0;
|
||||
this.end = this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a "slice" of the file. Since Cordova Files don't contain the actual
|
||||
* content, this really returns a File with adjusted start and end.
|
||||
* Slices of slices are supported.
|
||||
* start {Number} The index at which to start the slice (inclusive).
|
||||
* end {Number} The index at which to end the slice (exclusive).
|
||||
*/
|
||||
File.prototype.slice = function(start, end) {
|
||||
var size = this.end - this.start;
|
||||
var newStart = 0;
|
||||
var newEnd = size;
|
||||
if (arguments.length) {
|
||||
if (start < 0) {
|
||||
newStart = Math.max(size + start, 0);
|
||||
} else {
|
||||
newStart = Math.min(size, start);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.length >= 2) {
|
||||
if (end < 0) {
|
||||
newEnd = Math.max(size + end, 0);
|
||||
} else {
|
||||
newEnd = Math.min(end, size);
|
||||
}
|
||||
}
|
||||
|
||||
var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
|
||||
newFile.start = this.start + newStart;
|
||||
newFile.end = this.start + newEnd;
|
||||
return newFile;
|
||||
};
|
||||
|
||||
|
||||
module.exports = File;
|
||||
|
||||
});
|
96
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
96
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileWriter = require('./FileWriter'),
|
||||
File = require('./File'),
|
||||
FileError = require('./FileError');
|
||||
|
||||
/**
|
||||
* An interface representing a file on the file system.
|
||||
*
|
||||
* {boolean} isFile always true (readonly)
|
||||
* {boolean} isDirectory always false (readonly)
|
||||
* {DOMString} name of the file, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the file (readonly)
|
||||
* {FileSystem} filesystem on which the file resides (readonly)
|
||||
*/
|
||||
var FileEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
// remove trailing slash if it is present
|
||||
if (fullPath && /\/$/.test(fullPath)) {
|
||||
fullPath = fullPath.substring(0, fullPath.length - 1);
|
||||
}
|
||||
if (nativeURL && /\/$/.test(nativeURL)) {
|
||||
nativeURL = nativeURL.substring(0, nativeURL.length - 1);
|
||||
}
|
||||
|
||||
FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
|
||||
};
|
||||
|
||||
utils.extend(FileEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new FileWriter associated with the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new FileWriter
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
|
||||
this.file(function(filePointer) {
|
||||
var writer = new FileWriter(filePointer);
|
||||
|
||||
if (writer.localURL === null || writer.localURL === "") {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(FileError.INVALID_STATE_ERR));
|
||||
}
|
||||
} else {
|
||||
if (successCallback) {
|
||||
successCallback(writer);
|
||||
}
|
||||
}
|
||||
}, errorCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a File that represents the current state of the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new File object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.file = function(successCallback, errorCallback) {
|
||||
var localURL = this.toInternalURL();
|
||||
var win = successCallback && function(f) {
|
||||
var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
|
||||
successCallback(file);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFileMetadata", [localURL]);
|
||||
};
|
||||
|
||||
|
||||
module.exports = FileEntry;
|
||||
|
||||
});
|
49
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
49
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileError
|
||||
*/
|
||||
function FileError(error) {
|
||||
this.code = error || null;
|
||||
}
|
||||
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
FileError.NOT_FOUND_ERR = 1;
|
||||
FileError.SECURITY_ERR = 2;
|
||||
FileError.ABORT_ERR = 3;
|
||||
|
||||
// Added by File API specification
|
||||
FileError.NOT_READABLE_ERR = 4;
|
||||
FileError.ENCODING_ERR = 5;
|
||||
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
FileError.INVALID_STATE_ERR = 7;
|
||||
FileError.SYNTAX_ERR = 8;
|
||||
FileError.INVALID_MODIFICATION_ERR = 9;
|
||||
FileError.QUOTA_EXCEEDED_ERR = 10;
|
||||
FileError.TYPE_MISMATCH_ERR = 11;
|
||||
FileError.PATH_EXISTS_ERR = 12;
|
||||
|
||||
module.exports = FileError;
|
||||
|
||||
});
|
292
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
292
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
modulemapper = require('cordova/modulemapper'),
|
||||
utils = require('cordova/utils'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent'),
|
||||
origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
|
||||
|
||||
/**
|
||||
* This class reads the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To read from the SD card, the file name is "sdcard/my_file.txt"
|
||||
* @constructor
|
||||
*/
|
||||
var FileReader = function() {
|
||||
this._readyState = 0;
|
||||
this._error = null;
|
||||
this._result = null;
|
||||
this._progress = null;
|
||||
this._localURL = '';
|
||||
this._realReader = origFileReader ? new origFileReader() : {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the maximum size to read at a time via the native API. The default value is a compromise between
|
||||
* minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
|
||||
* (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
|
||||
* OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
|
||||
*/
|
||||
FileReader.READ_CHUNK_SIZE = 256*1024;
|
||||
|
||||
// States
|
||||
FileReader.EMPTY = 0;
|
||||
FileReader.LOADING = 1;
|
||||
FileReader.DONE = 2;
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'readyState', function() {
|
||||
return this._localURL ? this._readyState : this._realReader.readyState;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'error', function() {
|
||||
return this._localURL ? this._error: this._realReader.error;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'result', function() {
|
||||
return this._localURL ? this._result: this._realReader.result;
|
||||
});
|
||||
|
||||
function defineEvent(eventName) {
|
||||
utils.defineGetterSetter(FileReader.prototype, eventName, function() {
|
||||
return this._realReader[eventName] || null;
|
||||
}, function(value) {
|
||||
this._realReader[eventName] = value;
|
||||
});
|
||||
}
|
||||
defineEvent('onloadstart'); // When the read starts.
|
||||
defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
|
||||
defineEvent('onload'); // When the read has successfully completed.
|
||||
defineEvent('onerror'); // When the read has failed (see errors).
|
||||
defineEvent('onloadend'); // When the request has completed (either in success or failure).
|
||||
defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
|
||||
|
||||
function initRead(reader, file) {
|
||||
// Already loading something
|
||||
if (reader.readyState == FileReader.LOADING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
reader._result = null;
|
||||
reader._error = null;
|
||||
reader._progress = 0;
|
||||
reader._readyState = FileReader.LOADING;
|
||||
|
||||
if (typeof file.localURL == 'string') {
|
||||
reader._localURL = file.localURL;
|
||||
} else {
|
||||
reader._localURL = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reader.onloadstart) {
|
||||
reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle incremental or final success.
|
||||
* Must be bound to the FileReader's this along with all but the last parameter,
|
||||
* e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
|
||||
* @param readType The name of the read function to call.
|
||||
* @param encoding Text encoding, or null if this is not a text type read.
|
||||
* @param offset Starting offset of the read.
|
||||
* @param totalSize Total number of bytes or chars to read.
|
||||
* @param accumulate A function that takes the callback result and accumulates it in this._result.
|
||||
* @param r Callback result returned by the last read exec() call, or null to begin reading.
|
||||
*/
|
||||
function readSuccessCallback(readType, encoding, offset, totalSize, accumulate, r) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof r !== "undefined") {
|
||||
accumulate(r);
|
||||
this._progress = Math.min(this._progress + FileReader.READ_CHUNK_SIZE, totalSize);
|
||||
|
||||
if (typeof this.onprogress === "function") {
|
||||
this.onprogress(new ProgressEvent("progress", {loaded:this._progress, total:totalSize}));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof r === "undefined" || this._progress < totalSize) {
|
||||
var execArgs = [
|
||||
this._localURL,
|
||||
offset + this._progress,
|
||||
offset + this._progress + Math.min(totalSize - this._progress, FileReader.READ_CHUNK_SIZE)];
|
||||
if (encoding) {
|
||||
execArgs.splice(1, 0, encoding);
|
||||
}
|
||||
exec(
|
||||
readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
|
||||
readFailureCallback.bind(this),
|
||||
"File", readType, execArgs);
|
||||
} else {
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
if (typeof this.onload === "function") {
|
||||
this.onload(new ProgressEvent("load", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle errors.
|
||||
* Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
|
||||
*/
|
||||
function readFailureCallback(e) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
this._result = null;
|
||||
this._error = new FileError(e);
|
||||
|
||||
if (typeof this.onerror === "function") {
|
||||
this.onerror(new ProgressEvent("error", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort reading file.
|
||||
*/
|
||||
FileReader.prototype.abort = function() {
|
||||
if (origFileReader && !this._localURL) {
|
||||
return this._realReader.abort();
|
||||
}
|
||||
this._result = null;
|
||||
|
||||
if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === 'function') {
|
||||
this.onabort(new ProgressEvent('abort', {target:this}));
|
||||
}
|
||||
// If load end callback
|
||||
if (typeof this.onloadend === 'function') {
|
||||
this.onloadend(new ProgressEvent('loadend', {target:this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Read text file.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
|
||||
*/
|
||||
FileReader.prototype.readAsText = function(file, encoding) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsText(file, encoding);
|
||||
}
|
||||
|
||||
// Default encoding is UTF-8
|
||||
var enc = encoding ? encoding : "UTF-8";
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsText", enc, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read file and return data as a base64 encoded data url.
|
||||
* A data url is of the form:
|
||||
* data:[<mediatype>][;base64],<data>
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsDataURL = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsDataURL", null, file.start, totalSize, function(r) {
|
||||
var commaIndex = r.indexOf(',');
|
||||
if (this._progress === 0) {
|
||||
this._result = r;
|
||||
} else {
|
||||
this._result += r.substring(commaIndex + 1);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsBinaryString = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsBinaryString(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsBinaryString", null, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsArrayBuffer = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsArrayBuffer", null, file.start, totalSize, function(r) {
|
||||
var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
|
||||
resultArray.set(new Uint8Array(r), this._progress);
|
||||
this._result = resultArray.buffer;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = FileReader;
|
||||
|
||||
});
|
58
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
58
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
|
||||
/**
|
||||
* An interface representing a file system
|
||||
*
|
||||
* @constructor
|
||||
* {DOMString} name the unique name of the file system (readonly)
|
||||
* {DirectoryEntry} root directory of the file system (readonly)
|
||||
*/
|
||||
var FileSystem = function(name, root) {
|
||||
this.name = name;
|
||||
if (root) {
|
||||
this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
|
||||
} else {
|
||||
this.root = new DirectoryEntry(this.name, '/', this);
|
||||
}
|
||||
};
|
||||
|
||||
FileSystem.prototype.__format__ = function(fullPath, nativeUrl) {
|
||||
return fullPath;
|
||||
};
|
||||
|
||||
FileSystem.prototype.toJSON = function() {
|
||||
return "<FileSystem: " + this.name + ">";
|
||||
};
|
||||
|
||||
// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
|
||||
FileSystem.encodeURIPath = function(path) {
|
||||
// Because # is a valid filename character, it must be encoded to prevent part of the
|
||||
// path from being parsed as a URI fragment.
|
||||
return encodeURI(path).replace(/#/g, '%23');
|
||||
};
|
||||
|
||||
module.exports = FileSystem;
|
||||
|
||||
});
|
44
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
44
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options to customize the HTTP request used to upload files.
|
||||
* @constructor
|
||||
* @param fileKey {String} Name of file request parameter.
|
||||
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
|
||||
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
|
||||
* @param params {Object} Object with key: value params to send to the server.
|
||||
* @param headers {Object} Keys are header names, values are header values. Multiple
|
||||
* headers of the same name are not supported.
|
||||
*/
|
||||
var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
|
||||
this.fileKey = fileKey || null;
|
||||
this.fileName = fileName || null;
|
||||
this.mimeType = mimeType || null;
|
||||
this.params = params || null;
|
||||
this.headers = headers || null;
|
||||
this.httpMethod = httpMethod || null;
|
||||
};
|
||||
|
||||
module.exports = FileUploadOptions;
|
||||
|
||||
});
|
32
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
32
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileUploadResult
|
||||
* @constructor
|
||||
*/
|
||||
module.exports = function FileUploadResult(size, code, content) {
|
||||
this.bytesSent = size;
|
||||
this.responseCode = code;
|
||||
this.response = content;
|
||||
};
|
||||
});
|
327
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
327
platforms/android/assets/www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent');
|
||||
|
||||
/**
|
||||
* This class writes to the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To write to the SD card, the file name is "sdcard/my_file.txt"
|
||||
*
|
||||
* @constructor
|
||||
* @param file {File} File object containing file properties
|
||||
* @param append if true write to the end of the file, otherwise overwrite the file
|
||||
*/
|
||||
var FileWriter = function(file) {
|
||||
this.fileName = "";
|
||||
this.length = 0;
|
||||
if (file) {
|
||||
this.localURL = file.localURL || file;
|
||||
this.length = file.size || 0;
|
||||
}
|
||||
// default is to write at the beginning of the file
|
||||
this.position = 0;
|
||||
|
||||
this.readyState = 0; // EMPTY
|
||||
|
||||
this.result = null;
|
||||
|
||||
// Error
|
||||
this.error = null;
|
||||
|
||||
// Event handlers
|
||||
this.onwritestart = null; // When writing starts
|
||||
this.onprogress = null; // While writing the file, and reporting partial file data
|
||||
this.onwrite = null; // When the write has successfully completed.
|
||||
this.onwriteend = null; // When the request has completed (either in success or failure).
|
||||
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
|
||||
this.onerror = null; // When the write has failed (see errors).
|
||||
};
|
||||
|
||||
// States
|
||||
FileWriter.INIT = 0;
|
||||
FileWriter.WRITING = 1;
|
||||
FileWriter.DONE = 2;
|
||||
|
||||
/**
|
||||
* Abort writing file.
|
||||
*/
|
||||
FileWriter.prototype.abort = function() {
|
||||
// check for invalid state
|
||||
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// set error
|
||||
this.error = new FileError(FileError.ABORT_ERR);
|
||||
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === "function") {
|
||||
this.onabort(new ProgressEvent("abort", {"target":this}));
|
||||
}
|
||||
|
||||
// If write end callback
|
||||
if (typeof this.onwriteend === "function") {
|
||||
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes data to the file
|
||||
*
|
||||
* @param data text or blob to be written
|
||||
* @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
|
||||
*/
|
||||
FileWriter.prototype.write = function(data, isPendingBlobReadResult) {
|
||||
|
||||
var that=this;
|
||||
var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
|
||||
var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
|
||||
var isBinary;
|
||||
|
||||
// Check to see if the incoming data is a blob
|
||||
if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function() {
|
||||
// Call this method again, with the arraybuffer as argument
|
||||
FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
|
||||
};
|
||||
fileReader.onerror = function () {
|
||||
// DONE state
|
||||
that.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
that.error = this.error;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof that.onerror === "function") {
|
||||
that.onerror(new ProgressEvent("error", {"target":that}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof that.onwriteend === "function") {
|
||||
that.onwriteend(new ProgressEvent("writeend", {"target":that}));
|
||||
}
|
||||
};
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
if (supportsBinary) {
|
||||
fileReader.readAsArrayBuffer(data);
|
||||
} else {
|
||||
fileReader.readAsText(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark data type for safer transport over the binary bridge
|
||||
isBinary = supportsBinary && (data instanceof ArrayBuffer);
|
||||
if (isBinary && cordova.platformId === "windowsphone") {
|
||||
// create a plain array, using the keys from the Uint8Array view so that we can serialize it
|
||||
data = Array.apply(null, new Uint8Array(data));
|
||||
}
|
||||
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// position always increases by bytes written because file would be extended
|
||||
me.position += r;
|
||||
// The length of the file is now where we are done writing.
|
||||
|
||||
me.length = me.position;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "write", [this.localURL, data, this.position, isBinary]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the file pointer to the location specified.
|
||||
*
|
||||
* If the offset is a negative number the position of the file
|
||||
* pointer is rewound. If the offset is greater than the file
|
||||
* size the position is set to the end of the file.
|
||||
*
|
||||
* @param offset is the location to move the file pointer to.
|
||||
*/
|
||||
FileWriter.prototype.seek = function(offset) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
if (!offset && offset !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See back from end of file.
|
||||
if (offset < 0) {
|
||||
this.position = Math.max(offset + this.length, 0);
|
||||
}
|
||||
// Offset is bigger than file size so set position
|
||||
// to the end of the file.
|
||||
else if (offset > this.length) {
|
||||
this.position = this.length;
|
||||
}
|
||||
// Offset is between 0 and file size so set the position
|
||||
// to start writing.
|
||||
else {
|
||||
this.position = offset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Truncates the file to the size specified.
|
||||
*
|
||||
* @param size to chop the file at.
|
||||
*/
|
||||
FileWriter.prototype.truncate = function(size) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Update the length of the file
|
||||
me.length = r;
|
||||
me.position = Math.min(me.position, r);
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "truncate", [this.localURL, size]);
|
||||
};
|
||||
|
||||
module.exports = FileWriter;
|
||||
|
||||
});
|
39
platforms/android/assets/www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
39
platforms/android/assets/www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supplies arguments to methods that lookup or create files and directories.
|
||||
*
|
||||
* @param create
|
||||
* {boolean} file or directory if it doesn't exist
|
||||
* @param exclusive
|
||||
* {boolean} used with create; if true the command will fail if
|
||||
* target path exists
|
||||
*/
|
||||
function Flags(create, exclusive) {
|
||||
this.create = create || false;
|
||||
this.exclusive = exclusive || false;
|
||||
}
|
||||
|
||||
module.exports = Flags;
|
||||
|
||||
});
|
26
platforms/android/assets/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
26
platforms/android/assets/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
exports.TEMPORARY = 0;
|
||||
exports.PERSISTENT = 1;
|
||||
|
||||
});
|
43
platforms/android/assets/www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
43
platforms/android/assets/www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Information about the state of the file or directory
|
||||
*
|
||||
* {Date} modificationTime (readonly)
|
||||
*/
|
||||
var Metadata = function(metadata) {
|
||||
if (typeof metadata == "object") {
|
||||
this.modificationTime = new Date(metadata.modificationTime);
|
||||
this.size = metadata.size || 0;
|
||||
} else if (typeof metadata == "undefined") {
|
||||
this.modificationTime = null;
|
||||
this.size = 0;
|
||||
} else {
|
||||
/* Backwards compatiblity with platforms that only return a timestamp */
|
||||
this.modificationTime = new Date(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Metadata;
|
||||
|
||||
});
|
70
platforms/android/assets/www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
70
platforms/android/assets/www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
|
||||
// Feature test: See if we can instantiate a native ProgressEvent;
|
||||
// if so, use that approach,
|
||||
// otherwise fill-in with our own implementation.
|
||||
//
|
||||
// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
|
||||
var ProgressEvent = (function() {
|
||||
/*
|
||||
var createEvent = function(data) {
|
||||
var event = document.createEvent('Events');
|
||||
event.initEvent('ProgressEvent', false, false);
|
||||
if (data) {
|
||||
for (var i in data) {
|
||||
if (data.hasOwnProperty(i)) {
|
||||
event[i] = data[i];
|
||||
}
|
||||
}
|
||||
if (data.target) {
|
||||
// TODO: cannot call <some_custom_object>.dispatchEvent
|
||||
// need to first figure out how to implement EventTarget
|
||||
}
|
||||
}
|
||||
return event;
|
||||
};
|
||||
try {
|
||||
var ev = createEvent({type:"abort",target:document});
|
||||
return function ProgressEvent(type, data) {
|
||||
data.type = type;
|
||||
return createEvent(data);
|
||||
};
|
||||
} catch(e){
|
||||
*/
|
||||
return function ProgressEvent(type, dict) {
|
||||
this.type = type;
|
||||
this.bubbles = false;
|
||||
this.cancelBubble = false;
|
||||
this.cancelable = false;
|
||||
this.lengthComputable = false;
|
||||
this.loaded = dict && dict.loaded ? dict.loaded : 0;
|
||||
this.total = dict && dict.total ? dict.total : 0;
|
||||
this.target = dict && dict.target ? dict.target : null;
|
||||
};
|
||||
//}
|
||||
})();
|
||||
|
||||
module.exports = ProgressEvent;
|
||||
|
||||
});
|
52
platforms/android/assets/www/plugins/cordova-plugin-file/www/android/FileSystem.js
vendored
Normal file
52
platforms/android/assets/www/plugins/cordova-plugin-file/www/android/FileSystem.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
FILESYSTEM_PROTOCOL = "cdvfile";
|
||||
|
||||
module.exports = {
|
||||
__format__: function(fullPath, nativeUrl) {
|
||||
var path;
|
||||
var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
|
||||
if (contentUrlMatch) {
|
||||
// When available, use the path from a native content URL, which was already encoded by Android.
|
||||
// This is necessary because JavaScript's encodeURI() does not encode as many characters as
|
||||
// Android, which can result in permission exceptions when the encoding of a content URI
|
||||
// doesn't match the string for which permission was originally granted.
|
||||
path = nativeUrl.substring(contentUrlMatch[0].length - 1);
|
||||
} else {
|
||||
path = FileSystem.encodeURIPath(fullPath);
|
||||
if (!/^\//.test(path)) {
|
||||
path = '/' + path;
|
||||
}
|
||||
|
||||
var m = /\?.*/.exec(nativeUrl);
|
||||
if (m) {
|
||||
path += m[0];
|
||||
}
|
||||
}
|
||||
|
||||
return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
29
platforms/android/assets/www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
29
platforms/android/assets/www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = function () {
|
||||
// window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
|
||||
// possibly a good flag to indicate that we're running in Chrome
|
||||
return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
|
||||
};
|
||||
|
||||
});
|
66
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
66
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var channel = require('cordova/channel');
|
||||
|
||||
exports.file = {
|
||||
// Read-only directory where the application is installed.
|
||||
applicationDirectory: null,
|
||||
// Root of app's private writable storage
|
||||
applicationStorageDirectory: null,
|
||||
// Where to put app-specific data files.
|
||||
dataDirectory: null,
|
||||
// Cached files that should survive app restarts.
|
||||
// Apps should not rely on the OS to delete files in here.
|
||||
cacheDirectory: null,
|
||||
// Android: the application space on external storage.
|
||||
externalApplicationStorageDirectory: null,
|
||||
// Android: Where to put app-specific data files on external storage.
|
||||
externalDataDirectory: null,
|
||||
// Android: the application cache on external storage.
|
||||
externalCacheDirectory: null,
|
||||
// Android: the external storage (SD card) root.
|
||||
externalRootDirectory: null,
|
||||
// iOS: Temp directory that the OS can clear at will.
|
||||
tempDirectory: null,
|
||||
// iOS: Holds app-specific files that should be synced (e.g. to iCloud).
|
||||
syncedDataDirectory: null,
|
||||
// iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
|
||||
documentsDirectory: null,
|
||||
// BlackBerry10: Files globally available to all apps
|
||||
sharedDirectory: null
|
||||
};
|
||||
|
||||
channel.waitForInitialization('onFileSystemPathsReady');
|
||||
channel.onCordovaReady.subscribe(function() {
|
||||
function after(paths) {
|
||||
for (var k in paths) {
|
||||
exports.file[k] = paths[k];
|
||||
}
|
||||
channel.initializationComplete('onFileSystemPathsReady');
|
||||
}
|
||||
exec(after, null, 'File', 'requestAllPaths', []);
|
||||
});
|
||||
|
||||
|
||||
});
|
48
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
48
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Map of fsName -> FileSystem.
|
||||
var fsMap = null;
|
||||
var FileSystem = require('./FileSystem');
|
||||
var exec = require('cordova/exec');
|
||||
|
||||
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
|
||||
require('./fileSystems').getFs = function(name, callback) {
|
||||
function success(response) {
|
||||
fsMap = {};
|
||||
for (var i = 0; i < response.length; ++i) {
|
||||
var fsRoot = response[i];
|
||||
var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
|
||||
fsMap[fs.name] = fs;
|
||||
}
|
||||
callback(fsMap[name]);
|
||||
}
|
||||
|
||||
if (fsMap) {
|
||||
callback(fsMap[name]);
|
||||
} else {
|
||||
exec(success, null, "File", "requestAllFileSystems", []);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
28
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystems.js
vendored
Normal file
28
platforms/android/assets/www/plugins/cordova-plugin-file/www/fileSystems.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
|
||||
module.exports.getFs = function(name, callback) {
|
||||
callback(null);
|
||||
};
|
||||
|
||||
});
|
85
platforms/android/assets/www/plugins/cordova-plugin-file/www/requestFileSystem.js
vendored
Normal file
85
platforms/android/assets/www/plugins/cordova-plugin-file/www/requestFileSystem.js
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
(function() {
|
||||
//For browser platform: not all browsers use this file.
|
||||
function checkBrowser() {
|
||||
if (cordova.platformId === "browser" && require('./isChrome')()) {
|
||||
module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (checkBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
FileError = require('./FileError'),
|
||||
FileSystem = require('./FileSystem'),
|
||||
exec = require('cordova/exec');
|
||||
var fileSystems = require('./fileSystems');
|
||||
|
||||
/**
|
||||
* Request a file system in which to store application data.
|
||||
* @param type local file system type
|
||||
* @param size indicates how much storage space, in bytes, the application expects to need
|
||||
* @param successCallback invoked with a FileSystem object
|
||||
* @param errorCallback invoked if error occurs retrieving file system
|
||||
*/
|
||||
var requestFileSystem = function(type, size, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
|
||||
var fail = function(code) {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(code));
|
||||
}
|
||||
};
|
||||
|
||||
if (type < 0) {
|
||||
fail(FileError.SYNTAX_ERR);
|
||||
} else {
|
||||
// if successful, return a FileSystem object
|
||||
var success = function(file_system) {
|
||||
if (file_system) {
|
||||
if (successCallback) {
|
||||
fileSystems.getFs(file_system.name, function(fs) {
|
||||
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
|
||||
if (!fs) {
|
||||
fs = new FileSystem(file_system.name, file_system.root);
|
||||
}
|
||||
successCallback(fs);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no FileSystem object returned
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
};
|
||||
exec(success, fail, "File", "requestFileSystem", [type, size]);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = requestFileSystem;
|
||||
})();
|
||||
|
||||
});
|
95
platforms/android/assets/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
vendored
Normal file
95
platforms/android/assets/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
(function() {
|
||||
//For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
|
||||
function checkBrowser() {
|
||||
if (cordova.platformId === "browser" && require('./isChrome')()) {
|
||||
module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (checkBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
DirectoryEntry = require('./DirectoryEntry'),
|
||||
FileEntry = require('./FileEntry'),
|
||||
FileError = require('./FileError'),
|
||||
exec = require('cordova/exec');
|
||||
var fileSystems = require('./fileSystems');
|
||||
|
||||
/**
|
||||
* Look up file system Entry referred to by local URI.
|
||||
* @param {DOMString} uri URI referring to a local file or directory
|
||||
* @param successCallback invoked with Entry object corresponding to URI
|
||||
* @param errorCallback invoked if error occurs retrieving file system entry
|
||||
*/
|
||||
module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function(uri, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
|
||||
// error callback
|
||||
var fail = function(error) {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(error));
|
||||
}
|
||||
};
|
||||
// sanity check for 'not:valid:filename' or '/not:valid:filename'
|
||||
// file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
|
||||
if(!uri || uri.split(":").length > 2) {
|
||||
setTimeout( function() {
|
||||
fail(FileError.ENCODING_ERR);
|
||||
},0);
|
||||
return;
|
||||
}
|
||||
// if successful, return either a file or directory entry
|
||||
var success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary');
|
||||
fileSystems.getFs(fsName, function(fs) {
|
||||
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
|
||||
if (!fs) {
|
||||
fs = new FileSystem(fsName, {name:"", fullPath:"/"});
|
||||
}
|
||||
var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
};
|
||||
|
||||
exec(success, fail, "File", "resolveLocalFileSystemURI", [uri]);
|
||||
};
|
||||
|
||||
module.exports.resolveLocalFileSystemURI = function() {
|
||||
console.log("resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.");
|
||||
module.exports.resolveLocalFileSystemURL.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
});
|
120
platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
120
platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileError = require('./FileError'),
|
||||
DirectoryReader = require('./DirectoryReader');
|
||||
|
||||
/**
|
||||
* An interface representing a directory on the file system.
|
||||
*
|
||||
* {boolean} isFile always false (readonly)
|
||||
* {boolean} isDirectory always true (readonly)
|
||||
* {DOMString} name of the directory, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the directory (readonly)
|
||||
* {FileSystem} filesystem on which the directory resides (readonly)
|
||||
*/
|
||||
var DirectoryEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
|
||||
// add trailing slash if it is missing
|
||||
if ((fullPath) && !/\/$/.test(fullPath)) {
|
||||
fullPath += "/";
|
||||
}
|
||||
// add trailing slash if it is missing
|
||||
if (nativeURL && !/\/$/.test(nativeURL)) {
|
||||
nativeURL += "/";
|
||||
}
|
||||
DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
|
||||
};
|
||||
|
||||
utils.extend(DirectoryEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new DirectoryReader to read entries from this directory
|
||||
*/
|
||||
DirectoryEntry.prototype.createReader = function() {
|
||||
return new DirectoryReader(this.toInternalURL());
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a directory
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
|
||||
* @param {Flags} options to create or exclusively create the directory
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getDirectory", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a directory and all of it's contents
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "removeRecursively", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a file
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
|
||||
* @param {Flags} options to create or exclusively create the file
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var FileEntry = require('./FileEntry');
|
||||
var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFile", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryEntry;
|
||||
|
||||
});
|
76
platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
76
platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError') ;
|
||||
|
||||
/**
|
||||
* An interface that lists the files and directories in a directory.
|
||||
*/
|
||||
function DirectoryReader(localURL) {
|
||||
this.localURL = localURL || null;
|
||||
this.hasReadEntries = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of entries from a directory.
|
||||
*
|
||||
* @param {Function} successCallback is called with a list of entries
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
|
||||
// If we've already read and passed on this directory's entries, return an empty list.
|
||||
if (this.hasReadEntries) {
|
||||
successCallback([]);
|
||||
return;
|
||||
}
|
||||
var reader = this;
|
||||
var win = typeof successCallback !== 'function' ? null : function(result) {
|
||||
var retVal = [];
|
||||
for (var i=0; i<result.length; i++) {
|
||||
var entry = null;
|
||||
if (result[i].isDirectory) {
|
||||
entry = new (require('./DirectoryEntry'))();
|
||||
}
|
||||
else if (result[i].isFile) {
|
||||
entry = new (require('./FileEntry'))();
|
||||
}
|
||||
entry.isDirectory = result[i].isDirectory;
|
||||
entry.isFile = result[i].isFile;
|
||||
entry.name = result[i].name;
|
||||
entry.fullPath = result[i].fullPath;
|
||||
entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
|
||||
entry.nativeURL = result[i].nativeURL;
|
||||
retVal.push(entry);
|
||||
}
|
||||
reader.hasReadEntries = true;
|
||||
successCallback(retVal);
|
||||
};
|
||||
var fail = typeof errorCallback !== 'function' ? null : function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "readEntries", [this.localURL]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryReader;
|
||||
|
||||
});
|
265
platforms/android/platform_www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
265
platforms/android/platform_www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
Metadata = require('./Metadata');
|
||||
|
||||
/**
|
||||
* Represents a file or directory on the local file system.
|
||||
*
|
||||
* @param isFile
|
||||
* {boolean} true if Entry is a file (readonly)
|
||||
* @param isDirectory
|
||||
* {boolean} true if Entry is a directory (readonly)
|
||||
* @param name
|
||||
* {DOMString} name of the file or directory, excluding the path
|
||||
* leading to it (readonly)
|
||||
* @param fullPath
|
||||
* {DOMString} the absolute full path to the file or directory
|
||||
* (readonly)
|
||||
* @param fileSystem
|
||||
* {FileSystem} the filesystem on which this entry resides
|
||||
* (readonly)
|
||||
* @param nativeURL
|
||||
* {DOMString} an alternate URL which can be used by native
|
||||
* webview controls, for example media players.
|
||||
* (optional, readonly)
|
||||
*/
|
||||
function Entry(isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
|
||||
this.isFile = !!isFile;
|
||||
this.isDirectory = !!isDirectory;
|
||||
this.name = name || '';
|
||||
this.fullPath = fullPath || '';
|
||||
this.filesystem = fileSystem || null;
|
||||
this.nativeURL = nativeURL || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
*/
|
||||
Entry.prototype.getMetadata = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
|
||||
var success = successCallback && function(entryMetadata) {
|
||||
var metadata = new Metadata({
|
||||
size: entryMetadata.size,
|
||||
modificationTime: entryMetadata.lastModifiedDate
|
||||
});
|
||||
successCallback(metadata);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(success, fail, "File", "getFileMetadata", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
* @param metadataObject
|
||||
* {Object} keys and values to set
|
||||
*/
|
||||
Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
|
||||
argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
|
||||
exec(successCallback, errorCallback, "File", "setMetadata", [this.toInternalURL(), metadataObject]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a file or directory to a new location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to move this entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new DirectoryEntry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "moveTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a directory to a different location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to copy the entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new Entry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
// success callback
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "copyTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be passed across the bridge to identify this entry.
|
||||
*/
|
||||
Entry.prototype.toInternalURL = function() {
|
||||
if (this.filesystem && this.filesystem.__format__) {
|
||||
return this.filesystem.__format__(this.fullPath, this.nativeURL);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be used to identify this entry.
|
||||
* Use a URL that can be used to as the src attribute of a <video> or
|
||||
* <audio> tag. If that is not possible, construct a cdvfile:// URL.
|
||||
*/
|
||||
Entry.prototype.toURL = function() {
|
||||
if (this.nativeURL) {
|
||||
return this.nativeURL;
|
||||
}
|
||||
// fullPath attribute may contain the full URL in the case that
|
||||
// toInternalURL fails.
|
||||
return this.toInternalURL() || "file://localhost" + this.fullPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
|
||||
* cdvfile:// URL, and this method was necessary to obtain URLs usable by the
|
||||
* webview.
|
||||
* See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
|
||||
* and CB-6300.
|
||||
*/
|
||||
Entry.prototype.toNativeURL = function() {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a URI that can be used to identify this entry.
|
||||
*
|
||||
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
|
||||
* @return uri
|
||||
*/
|
||||
Entry.prototype.toURI = function(mimeType) {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a file or directory. It is an error to attempt to delete a
|
||||
* directory that is not empty. It is an error to attempt to delete a
|
||||
* root directory of a file system.
|
||||
*
|
||||
* @param successCallback {Function} called with no parameters
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.remove = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.remove', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "remove", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Look up the parent DirectoryEntry of this entry.
|
||||
*
|
||||
* @param successCallback {Function} called with the parent DirectoryEntry object
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.getParent = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getParent', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getParent", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
module.exports = Entry;
|
||||
|
||||
});
|
82
platforms/android/platform_www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
82
platforms/android/platform_www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
cordova.define("cordova-plugin-file.File", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* name {DOMString} name of the file, without path information
|
||||
* fullPath {DOMString} the full path of the file, including the name
|
||||
* type {DOMString} mime type
|
||||
* lastModifiedDate {Date} last modified date
|
||||
* size {Number} size of the file in bytes
|
||||
*/
|
||||
|
||||
var File = function(name, localURL, type, lastModifiedDate, size){
|
||||
this.name = name || '';
|
||||
this.localURL = localURL || null;
|
||||
this.type = type || null;
|
||||
this.lastModified = lastModifiedDate || null;
|
||||
// For backwards compatibility, store the timestamp in lastModifiedDate as well
|
||||
this.lastModifiedDate = lastModifiedDate || null;
|
||||
this.size = size || 0;
|
||||
|
||||
// These store the absolute start and end for slicing the file.
|
||||
this.start = 0;
|
||||
this.end = this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a "slice" of the file. Since Cordova Files don't contain the actual
|
||||
* content, this really returns a File with adjusted start and end.
|
||||
* Slices of slices are supported.
|
||||
* start {Number} The index at which to start the slice (inclusive).
|
||||
* end {Number} The index at which to end the slice (exclusive).
|
||||
*/
|
||||
File.prototype.slice = function(start, end) {
|
||||
var size = this.end - this.start;
|
||||
var newStart = 0;
|
||||
var newEnd = size;
|
||||
if (arguments.length) {
|
||||
if (start < 0) {
|
||||
newStart = Math.max(size + start, 0);
|
||||
} else {
|
||||
newStart = Math.min(size, start);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.length >= 2) {
|
||||
if (end < 0) {
|
||||
newEnd = Math.max(size + end, 0);
|
||||
} else {
|
||||
newEnd = Math.min(end, size);
|
||||
}
|
||||
}
|
||||
|
||||
var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
|
||||
newFile.start = this.start + newStart;
|
||||
newFile.end = this.start + newEnd;
|
||||
return newFile;
|
||||
};
|
||||
|
||||
|
||||
module.exports = File;
|
||||
|
||||
});
|
96
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
96
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileWriter = require('./FileWriter'),
|
||||
File = require('./File'),
|
||||
FileError = require('./FileError');
|
||||
|
||||
/**
|
||||
* An interface representing a file on the file system.
|
||||
*
|
||||
* {boolean} isFile always true (readonly)
|
||||
* {boolean} isDirectory always false (readonly)
|
||||
* {DOMString} name of the file, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the file (readonly)
|
||||
* {FileSystem} filesystem on which the file resides (readonly)
|
||||
*/
|
||||
var FileEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
// remove trailing slash if it is present
|
||||
if (fullPath && /\/$/.test(fullPath)) {
|
||||
fullPath = fullPath.substring(0, fullPath.length - 1);
|
||||
}
|
||||
if (nativeURL && /\/$/.test(nativeURL)) {
|
||||
nativeURL = nativeURL.substring(0, nativeURL.length - 1);
|
||||
}
|
||||
|
||||
FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
|
||||
};
|
||||
|
||||
utils.extend(FileEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new FileWriter associated with the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new FileWriter
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
|
||||
this.file(function(filePointer) {
|
||||
var writer = new FileWriter(filePointer);
|
||||
|
||||
if (writer.localURL === null || writer.localURL === "") {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(FileError.INVALID_STATE_ERR));
|
||||
}
|
||||
} else {
|
||||
if (successCallback) {
|
||||
successCallback(writer);
|
||||
}
|
||||
}
|
||||
}, errorCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a File that represents the current state of the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new File object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.file = function(successCallback, errorCallback) {
|
||||
var localURL = this.toInternalURL();
|
||||
var win = successCallback && function(f) {
|
||||
var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
|
||||
successCallback(file);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFileMetadata", [localURL]);
|
||||
};
|
||||
|
||||
|
||||
module.exports = FileEntry;
|
||||
|
||||
});
|
49
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
49
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileError
|
||||
*/
|
||||
function FileError(error) {
|
||||
this.code = error || null;
|
||||
}
|
||||
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
FileError.NOT_FOUND_ERR = 1;
|
||||
FileError.SECURITY_ERR = 2;
|
||||
FileError.ABORT_ERR = 3;
|
||||
|
||||
// Added by File API specification
|
||||
FileError.NOT_READABLE_ERR = 4;
|
||||
FileError.ENCODING_ERR = 5;
|
||||
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
FileError.INVALID_STATE_ERR = 7;
|
||||
FileError.SYNTAX_ERR = 8;
|
||||
FileError.INVALID_MODIFICATION_ERR = 9;
|
||||
FileError.QUOTA_EXCEEDED_ERR = 10;
|
||||
FileError.TYPE_MISMATCH_ERR = 11;
|
||||
FileError.PATH_EXISTS_ERR = 12;
|
||||
|
||||
module.exports = FileError;
|
||||
|
||||
});
|
292
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
292
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
modulemapper = require('cordova/modulemapper'),
|
||||
utils = require('cordova/utils'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent'),
|
||||
origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
|
||||
|
||||
/**
|
||||
* This class reads the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To read from the SD card, the file name is "sdcard/my_file.txt"
|
||||
* @constructor
|
||||
*/
|
||||
var FileReader = function() {
|
||||
this._readyState = 0;
|
||||
this._error = null;
|
||||
this._result = null;
|
||||
this._progress = null;
|
||||
this._localURL = '';
|
||||
this._realReader = origFileReader ? new origFileReader() : {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the maximum size to read at a time via the native API. The default value is a compromise between
|
||||
* minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
|
||||
* (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
|
||||
* OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
|
||||
*/
|
||||
FileReader.READ_CHUNK_SIZE = 256*1024;
|
||||
|
||||
// States
|
||||
FileReader.EMPTY = 0;
|
||||
FileReader.LOADING = 1;
|
||||
FileReader.DONE = 2;
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'readyState', function() {
|
||||
return this._localURL ? this._readyState : this._realReader.readyState;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'error', function() {
|
||||
return this._localURL ? this._error: this._realReader.error;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'result', function() {
|
||||
return this._localURL ? this._result: this._realReader.result;
|
||||
});
|
||||
|
||||
function defineEvent(eventName) {
|
||||
utils.defineGetterSetter(FileReader.prototype, eventName, function() {
|
||||
return this._realReader[eventName] || null;
|
||||
}, function(value) {
|
||||
this._realReader[eventName] = value;
|
||||
});
|
||||
}
|
||||
defineEvent('onloadstart'); // When the read starts.
|
||||
defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
|
||||
defineEvent('onload'); // When the read has successfully completed.
|
||||
defineEvent('onerror'); // When the read has failed (see errors).
|
||||
defineEvent('onloadend'); // When the request has completed (either in success or failure).
|
||||
defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
|
||||
|
||||
function initRead(reader, file) {
|
||||
// Already loading something
|
||||
if (reader.readyState == FileReader.LOADING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
reader._result = null;
|
||||
reader._error = null;
|
||||
reader._progress = 0;
|
||||
reader._readyState = FileReader.LOADING;
|
||||
|
||||
if (typeof file.localURL == 'string') {
|
||||
reader._localURL = file.localURL;
|
||||
} else {
|
||||
reader._localURL = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reader.onloadstart) {
|
||||
reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle incremental or final success.
|
||||
* Must be bound to the FileReader's this along with all but the last parameter,
|
||||
* e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
|
||||
* @param readType The name of the read function to call.
|
||||
* @param encoding Text encoding, or null if this is not a text type read.
|
||||
* @param offset Starting offset of the read.
|
||||
* @param totalSize Total number of bytes or chars to read.
|
||||
* @param accumulate A function that takes the callback result and accumulates it in this._result.
|
||||
* @param r Callback result returned by the last read exec() call, or null to begin reading.
|
||||
*/
|
||||
function readSuccessCallback(readType, encoding, offset, totalSize, accumulate, r) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof r !== "undefined") {
|
||||
accumulate(r);
|
||||
this._progress = Math.min(this._progress + FileReader.READ_CHUNK_SIZE, totalSize);
|
||||
|
||||
if (typeof this.onprogress === "function") {
|
||||
this.onprogress(new ProgressEvent("progress", {loaded:this._progress, total:totalSize}));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof r === "undefined" || this._progress < totalSize) {
|
||||
var execArgs = [
|
||||
this._localURL,
|
||||
offset + this._progress,
|
||||
offset + this._progress + Math.min(totalSize - this._progress, FileReader.READ_CHUNK_SIZE)];
|
||||
if (encoding) {
|
||||
execArgs.splice(1, 0, encoding);
|
||||
}
|
||||
exec(
|
||||
readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
|
||||
readFailureCallback.bind(this),
|
||||
"File", readType, execArgs);
|
||||
} else {
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
if (typeof this.onload === "function") {
|
||||
this.onload(new ProgressEvent("load", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle errors.
|
||||
* Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
|
||||
*/
|
||||
function readFailureCallback(e) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
this._result = null;
|
||||
this._error = new FileError(e);
|
||||
|
||||
if (typeof this.onerror === "function") {
|
||||
this.onerror(new ProgressEvent("error", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort reading file.
|
||||
*/
|
||||
FileReader.prototype.abort = function() {
|
||||
if (origFileReader && !this._localURL) {
|
||||
return this._realReader.abort();
|
||||
}
|
||||
this._result = null;
|
||||
|
||||
if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === 'function') {
|
||||
this.onabort(new ProgressEvent('abort', {target:this}));
|
||||
}
|
||||
// If load end callback
|
||||
if (typeof this.onloadend === 'function') {
|
||||
this.onloadend(new ProgressEvent('loadend', {target:this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Read text file.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
|
||||
*/
|
||||
FileReader.prototype.readAsText = function(file, encoding) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsText(file, encoding);
|
||||
}
|
||||
|
||||
// Default encoding is UTF-8
|
||||
var enc = encoding ? encoding : "UTF-8";
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsText", enc, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read file and return data as a base64 encoded data url.
|
||||
* A data url is of the form:
|
||||
* data:[<mediatype>][;base64],<data>
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsDataURL = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsDataURL", null, file.start, totalSize, function(r) {
|
||||
var commaIndex = r.indexOf(',');
|
||||
if (this._progress === 0) {
|
||||
this._result = r;
|
||||
} else {
|
||||
this._result += r.substring(commaIndex + 1);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsBinaryString = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsBinaryString(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsBinaryString", null, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsArrayBuffer = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsArrayBuffer", null, file.start, totalSize, function(r) {
|
||||
var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
|
||||
resultArray.set(new Uint8Array(r), this._progress);
|
||||
this._result = resultArray.buffer;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = FileReader;
|
||||
|
||||
});
|
58
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
58
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
|
||||
/**
|
||||
* An interface representing a file system
|
||||
*
|
||||
* @constructor
|
||||
* {DOMString} name the unique name of the file system (readonly)
|
||||
* {DirectoryEntry} root directory of the file system (readonly)
|
||||
*/
|
||||
var FileSystem = function(name, root) {
|
||||
this.name = name;
|
||||
if (root) {
|
||||
this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
|
||||
} else {
|
||||
this.root = new DirectoryEntry(this.name, '/', this);
|
||||
}
|
||||
};
|
||||
|
||||
FileSystem.prototype.__format__ = function(fullPath, nativeUrl) {
|
||||
return fullPath;
|
||||
};
|
||||
|
||||
FileSystem.prototype.toJSON = function() {
|
||||
return "<FileSystem: " + this.name + ">";
|
||||
};
|
||||
|
||||
// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
|
||||
FileSystem.encodeURIPath = function(path) {
|
||||
// Because # is a valid filename character, it must be encoded to prevent part of the
|
||||
// path from being parsed as a URI fragment.
|
||||
return encodeURI(path).replace(/#/g, '%23');
|
||||
};
|
||||
|
||||
module.exports = FileSystem;
|
||||
|
||||
});
|
44
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
44
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options to customize the HTTP request used to upload files.
|
||||
* @constructor
|
||||
* @param fileKey {String} Name of file request parameter.
|
||||
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
|
||||
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
|
||||
* @param params {Object} Object with key: value params to send to the server.
|
||||
* @param headers {Object} Keys are header names, values are header values. Multiple
|
||||
* headers of the same name are not supported.
|
||||
*/
|
||||
var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
|
||||
this.fileKey = fileKey || null;
|
||||
this.fileName = fileName || null;
|
||||
this.mimeType = mimeType || null;
|
||||
this.params = params || null;
|
||||
this.headers = headers || null;
|
||||
this.httpMethod = httpMethod || null;
|
||||
};
|
||||
|
||||
module.exports = FileUploadOptions;
|
||||
|
||||
});
|
32
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
32
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileUploadResult
|
||||
* @constructor
|
||||
*/
|
||||
module.exports = function FileUploadResult(size, code, content) {
|
||||
this.bytesSent = size;
|
||||
this.responseCode = code;
|
||||
this.response = content;
|
||||
};
|
||||
});
|
327
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
327
platforms/android/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent');
|
||||
|
||||
/**
|
||||
* This class writes to the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To write to the SD card, the file name is "sdcard/my_file.txt"
|
||||
*
|
||||
* @constructor
|
||||
* @param file {File} File object containing file properties
|
||||
* @param append if true write to the end of the file, otherwise overwrite the file
|
||||
*/
|
||||
var FileWriter = function(file) {
|
||||
this.fileName = "";
|
||||
this.length = 0;
|
||||
if (file) {
|
||||
this.localURL = file.localURL || file;
|
||||
this.length = file.size || 0;
|
||||
}
|
||||
// default is to write at the beginning of the file
|
||||
this.position = 0;
|
||||
|
||||
this.readyState = 0; // EMPTY
|
||||
|
||||
this.result = null;
|
||||
|
||||
// Error
|
||||
this.error = null;
|
||||
|
||||
// Event handlers
|
||||
this.onwritestart = null; // When writing starts
|
||||
this.onprogress = null; // While writing the file, and reporting partial file data
|
||||
this.onwrite = null; // When the write has successfully completed.
|
||||
this.onwriteend = null; // When the request has completed (either in success or failure).
|
||||
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
|
||||
this.onerror = null; // When the write has failed (see errors).
|
||||
};
|
||||
|
||||
// States
|
||||
FileWriter.INIT = 0;
|
||||
FileWriter.WRITING = 1;
|
||||
FileWriter.DONE = 2;
|
||||
|
||||
/**
|
||||
* Abort writing file.
|
||||
*/
|
||||
FileWriter.prototype.abort = function() {
|
||||
// check for invalid state
|
||||
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// set error
|
||||
this.error = new FileError(FileError.ABORT_ERR);
|
||||
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === "function") {
|
||||
this.onabort(new ProgressEvent("abort", {"target":this}));
|
||||
}
|
||||
|
||||
// If write end callback
|
||||
if (typeof this.onwriteend === "function") {
|
||||
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes data to the file
|
||||
*
|
||||
* @param data text or blob to be written
|
||||
* @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
|
||||
*/
|
||||
FileWriter.prototype.write = function(data, isPendingBlobReadResult) {
|
||||
|
||||
var that=this;
|
||||
var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
|
||||
var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
|
||||
var isBinary;
|
||||
|
||||
// Check to see if the incoming data is a blob
|
||||
if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function() {
|
||||
// Call this method again, with the arraybuffer as argument
|
||||
FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
|
||||
};
|
||||
fileReader.onerror = function () {
|
||||
// DONE state
|
||||
that.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
that.error = this.error;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof that.onerror === "function") {
|
||||
that.onerror(new ProgressEvent("error", {"target":that}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof that.onwriteend === "function") {
|
||||
that.onwriteend(new ProgressEvent("writeend", {"target":that}));
|
||||
}
|
||||
};
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
if (supportsBinary) {
|
||||
fileReader.readAsArrayBuffer(data);
|
||||
} else {
|
||||
fileReader.readAsText(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark data type for safer transport over the binary bridge
|
||||
isBinary = supportsBinary && (data instanceof ArrayBuffer);
|
||||
if (isBinary && cordova.platformId === "windowsphone") {
|
||||
// create a plain array, using the keys from the Uint8Array view so that we can serialize it
|
||||
data = Array.apply(null, new Uint8Array(data));
|
||||
}
|
||||
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// position always increases by bytes written because file would be extended
|
||||
me.position += r;
|
||||
// The length of the file is now where we are done writing.
|
||||
|
||||
me.length = me.position;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "write", [this.localURL, data, this.position, isBinary]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the file pointer to the location specified.
|
||||
*
|
||||
* If the offset is a negative number the position of the file
|
||||
* pointer is rewound. If the offset is greater than the file
|
||||
* size the position is set to the end of the file.
|
||||
*
|
||||
* @param offset is the location to move the file pointer to.
|
||||
*/
|
||||
FileWriter.prototype.seek = function(offset) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
if (!offset && offset !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See back from end of file.
|
||||
if (offset < 0) {
|
||||
this.position = Math.max(offset + this.length, 0);
|
||||
}
|
||||
// Offset is bigger than file size so set position
|
||||
// to the end of the file.
|
||||
else if (offset > this.length) {
|
||||
this.position = this.length;
|
||||
}
|
||||
// Offset is between 0 and file size so set the position
|
||||
// to start writing.
|
||||
else {
|
||||
this.position = offset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Truncates the file to the size specified.
|
||||
*
|
||||
* @param size to chop the file at.
|
||||
*/
|
||||
FileWriter.prototype.truncate = function(size) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Update the length of the file
|
||||
me.length = r;
|
||||
me.position = Math.min(me.position, r);
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "truncate", [this.localURL, size]);
|
||||
};
|
||||
|
||||
module.exports = FileWriter;
|
||||
|
||||
});
|
39
platforms/android/platform_www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
39
platforms/android/platform_www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supplies arguments to methods that lookup or create files and directories.
|
||||
*
|
||||
* @param create
|
||||
* {boolean} file or directory if it doesn't exist
|
||||
* @param exclusive
|
||||
* {boolean} used with create; if true the command will fail if
|
||||
* target path exists
|
||||
*/
|
||||
function Flags(create, exclusive) {
|
||||
this.create = create || false;
|
||||
this.exclusive = exclusive || false;
|
||||
}
|
||||
|
||||
module.exports = Flags;
|
||||
|
||||
});
|
26
platforms/android/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
26
platforms/android/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
exports.TEMPORARY = 0;
|
||||
exports.PERSISTENT = 1;
|
||||
|
||||
});
|
43
platforms/android/platform_www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
43
platforms/android/platform_www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Information about the state of the file or directory
|
||||
*
|
||||
* {Date} modificationTime (readonly)
|
||||
*/
|
||||
var Metadata = function(metadata) {
|
||||
if (typeof metadata == "object") {
|
||||
this.modificationTime = new Date(metadata.modificationTime);
|
||||
this.size = metadata.size || 0;
|
||||
} else if (typeof metadata == "undefined") {
|
||||
this.modificationTime = null;
|
||||
this.size = 0;
|
||||
} else {
|
||||
/* Backwards compatiblity with platforms that only return a timestamp */
|
||||
this.modificationTime = new Date(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Metadata;
|
||||
|
||||
});
|
70
platforms/android/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
70
platforms/android/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
|
||||
// Feature test: See if we can instantiate a native ProgressEvent;
|
||||
// if so, use that approach,
|
||||
// otherwise fill-in with our own implementation.
|
||||
//
|
||||
// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
|
||||
var ProgressEvent = (function() {
|
||||
/*
|
||||
var createEvent = function(data) {
|
||||
var event = document.createEvent('Events');
|
||||
event.initEvent('ProgressEvent', false, false);
|
||||
if (data) {
|
||||
for (var i in data) {
|
||||
if (data.hasOwnProperty(i)) {
|
||||
event[i] = data[i];
|
||||
}
|
||||
}
|
||||
if (data.target) {
|
||||
// TODO: cannot call <some_custom_object>.dispatchEvent
|
||||
// need to first figure out how to implement EventTarget
|
||||
}
|
||||
}
|
||||
return event;
|
||||
};
|
||||
try {
|
||||
var ev = createEvent({type:"abort",target:document});
|
||||
return function ProgressEvent(type, data) {
|
||||
data.type = type;
|
||||
return createEvent(data);
|
||||
};
|
||||
} catch(e){
|
||||
*/
|
||||
return function ProgressEvent(type, dict) {
|
||||
this.type = type;
|
||||
this.bubbles = false;
|
||||
this.cancelBubble = false;
|
||||
this.cancelable = false;
|
||||
this.lengthComputable = false;
|
||||
this.loaded = dict && dict.loaded ? dict.loaded : 0;
|
||||
this.total = dict && dict.total ? dict.total : 0;
|
||||
this.target = dict && dict.target ? dict.target : null;
|
||||
};
|
||||
//}
|
||||
})();
|
||||
|
||||
module.exports = ProgressEvent;
|
||||
|
||||
});
|
52
platforms/android/platform_www/plugins/cordova-plugin-file/www/android/FileSystem.js
vendored
Normal file
52
platforms/android/platform_www/plugins/cordova-plugin-file/www/android/FileSystem.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
FILESYSTEM_PROTOCOL = "cdvfile";
|
||||
|
||||
module.exports = {
|
||||
__format__: function(fullPath, nativeUrl) {
|
||||
var path;
|
||||
var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
|
||||
if (contentUrlMatch) {
|
||||
// When available, use the path from a native content URL, which was already encoded by Android.
|
||||
// This is necessary because JavaScript's encodeURI() does not encode as many characters as
|
||||
// Android, which can result in permission exceptions when the encoding of a content URI
|
||||
// doesn't match the string for which permission was originally granted.
|
||||
path = nativeUrl.substring(contentUrlMatch[0].length - 1);
|
||||
} else {
|
||||
path = FileSystem.encodeURIPath(fullPath);
|
||||
if (!/^\//.test(path)) {
|
||||
path = '/' + path;
|
||||
}
|
||||
|
||||
var m = /\?.*/.exec(nativeUrl);
|
||||
if (m) {
|
||||
path += m[0];
|
||||
}
|
||||
}
|
||||
|
||||
return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
29
platforms/android/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
29
platforms/android/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = function () {
|
||||
// window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
|
||||
// possibly a good flag to indicate that we're running in Chrome
|
||||
return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
|
||||
};
|
||||
|
||||
});
|
66
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
66
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var channel = require('cordova/channel');
|
||||
|
||||
exports.file = {
|
||||
// Read-only directory where the application is installed.
|
||||
applicationDirectory: null,
|
||||
// Root of app's private writable storage
|
||||
applicationStorageDirectory: null,
|
||||
// Where to put app-specific data files.
|
||||
dataDirectory: null,
|
||||
// Cached files that should survive app restarts.
|
||||
// Apps should not rely on the OS to delete files in here.
|
||||
cacheDirectory: null,
|
||||
// Android: the application space on external storage.
|
||||
externalApplicationStorageDirectory: null,
|
||||
// Android: Where to put app-specific data files on external storage.
|
||||
externalDataDirectory: null,
|
||||
// Android: the application cache on external storage.
|
||||
externalCacheDirectory: null,
|
||||
// Android: the external storage (SD card) root.
|
||||
externalRootDirectory: null,
|
||||
// iOS: Temp directory that the OS can clear at will.
|
||||
tempDirectory: null,
|
||||
// iOS: Holds app-specific files that should be synced (e.g. to iCloud).
|
||||
syncedDataDirectory: null,
|
||||
// iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
|
||||
documentsDirectory: null,
|
||||
// BlackBerry10: Files globally available to all apps
|
||||
sharedDirectory: null
|
||||
};
|
||||
|
||||
channel.waitForInitialization('onFileSystemPathsReady');
|
||||
channel.onCordovaReady.subscribe(function() {
|
||||
function after(paths) {
|
||||
for (var k in paths) {
|
||||
exports.file[k] = paths[k];
|
||||
}
|
||||
channel.initializationComplete('onFileSystemPathsReady');
|
||||
}
|
||||
exec(after, null, 'File', 'requestAllPaths', []);
|
||||
});
|
||||
|
||||
|
||||
});
|
48
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
48
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Map of fsName -> FileSystem.
|
||||
var fsMap = null;
|
||||
var FileSystem = require('./FileSystem');
|
||||
var exec = require('cordova/exec');
|
||||
|
||||
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
|
||||
require('./fileSystems').getFs = function(name, callback) {
|
||||
function success(response) {
|
||||
fsMap = {};
|
||||
for (var i = 0; i < response.length; ++i) {
|
||||
var fsRoot = response[i];
|
||||
var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
|
||||
fsMap[fs.name] = fs;
|
||||
}
|
||||
callback(fsMap[name]);
|
||||
}
|
||||
|
||||
if (fsMap) {
|
||||
callback(fsMap[name]);
|
||||
} else {
|
||||
exec(success, null, "File", "requestAllFileSystems", []);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
28
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
vendored
Normal file
28
platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
|
||||
module.exports.getFs = function(name, callback) {
|
||||
callback(null);
|
||||
};
|
||||
|
||||
});
|
85
platforms/android/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
vendored
Normal file
85
platforms/android/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
(function() {
|
||||
//For browser platform: not all browsers use this file.
|
||||
function checkBrowser() {
|
||||
if (cordova.platformId === "browser" && require('./isChrome')()) {
|
||||
module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (checkBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
FileError = require('./FileError'),
|
||||
FileSystem = require('./FileSystem'),
|
||||
exec = require('cordova/exec');
|
||||
var fileSystems = require('./fileSystems');
|
||||
|
||||
/**
|
||||
* Request a file system in which to store application data.
|
||||
* @param type local file system type
|
||||
* @param size indicates how much storage space, in bytes, the application expects to need
|
||||
* @param successCallback invoked with a FileSystem object
|
||||
* @param errorCallback invoked if error occurs retrieving file system
|
||||
*/
|
||||
var requestFileSystem = function(type, size, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
|
||||
var fail = function(code) {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(code));
|
||||
}
|
||||
};
|
||||
|
||||
if (type < 0) {
|
||||
fail(FileError.SYNTAX_ERR);
|
||||
} else {
|
||||
// if successful, return a FileSystem object
|
||||
var success = function(file_system) {
|
||||
if (file_system) {
|
||||
if (successCallback) {
|
||||
fileSystems.getFs(file_system.name, function(fs) {
|
||||
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
|
||||
if (!fs) {
|
||||
fs = new FileSystem(file_system.name, file_system.root);
|
||||
}
|
||||
successCallback(fs);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no FileSystem object returned
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
};
|
||||
exec(success, fail, "File", "requestFileSystem", [type, size]);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = requestFileSystem;
|
||||
})();
|
||||
|
||||
});
|
95
platforms/android/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
vendored
Normal file
95
platforms/android/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
(function() {
|
||||
//For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
|
||||
function checkBrowser() {
|
||||
if (cordova.platformId === "browser" && require('./isChrome')()) {
|
||||
module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (checkBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
DirectoryEntry = require('./DirectoryEntry'),
|
||||
FileEntry = require('./FileEntry'),
|
||||
FileError = require('./FileError'),
|
||||
exec = require('cordova/exec');
|
||||
var fileSystems = require('./fileSystems');
|
||||
|
||||
/**
|
||||
* Look up file system Entry referred to by local URI.
|
||||
* @param {DOMString} uri URI referring to a local file or directory
|
||||
* @param successCallback invoked with Entry object corresponding to URI
|
||||
* @param errorCallback invoked if error occurs retrieving file system entry
|
||||
*/
|
||||
module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function(uri, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
|
||||
// error callback
|
||||
var fail = function(error) {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(error));
|
||||
}
|
||||
};
|
||||
// sanity check for 'not:valid:filename' or '/not:valid:filename'
|
||||
// file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
|
||||
if(!uri || uri.split(":").length > 2) {
|
||||
setTimeout( function() {
|
||||
fail(FileError.ENCODING_ERR);
|
||||
},0);
|
||||
return;
|
||||
}
|
||||
// if successful, return either a file or directory entry
|
||||
var success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary');
|
||||
fileSystems.getFs(fsName, function(fs) {
|
||||
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
|
||||
if (!fs) {
|
||||
fs = new FileSystem(fsName, {name:"", fullPath:"/"});
|
||||
}
|
||||
var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
};
|
||||
|
||||
exec(success, fail, "File", "resolveLocalFileSystemURI", [uri]);
|
||||
};
|
||||
|
||||
module.exports.resolveLocalFileSystemURI = function() {
|
||||
console.log("resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.");
|
||||
module.exports.resolveLocalFileSystemURL.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
});
|
BIN
platforms/android/res/drawable-xxhdpi/icon.png
Normal file
BIN
platforms/android/res/drawable-xxhdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
platforms/android/res/drawable-xxxhdpi/icon.png
Normal file
BIN
platforms/android/res/drawable-xxxhdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
@ -0,0 +1,286 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.cordova.CordovaResourceApi;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AssetFilesystem extends Filesystem {
|
||||
|
||||
private final AssetManager assetManager;
|
||||
|
||||
// A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
|
||||
// See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
|
||||
private static Object listCacheLock = new Object();
|
||||
private static boolean listCacheFromFile;
|
||||
private static Map<String, String[]> listCache;
|
||||
private static Map<String, Long> lengthCache;
|
||||
|
||||
private void lazyInitCaches() {
|
||||
synchronized (listCacheLock) {
|
||||
if (listCache == null) {
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
|
||||
listCache = (Map<String, String[]>) ois.readObject();
|
||||
lengthCache = (Map<String, Long>) ois.readObject();
|
||||
listCacheFromFile = true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// Asset manifest won't exist if the gradle hook isn't set up correctly.
|
||||
} finally {
|
||||
if (ois != null) {
|
||||
try {
|
||||
ois.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (listCache == null) {
|
||||
Log.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
|
||||
listCache = new HashMap<String, String[]>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String[] listAssets(String assetPath) throws IOException {
|
||||
if (assetPath.startsWith("/")) {
|
||||
assetPath = assetPath.substring(1);
|
||||
}
|
||||
if (assetPath.endsWith("/")) {
|
||||
assetPath = assetPath.substring(0, assetPath.length() - 1);
|
||||
}
|
||||
lazyInitCaches();
|
||||
String[] ret = listCache.get(assetPath);
|
||||
if (ret == null) {
|
||||
if (listCacheFromFile) {
|
||||
ret = new String[0];
|
||||
} else {
|
||||
ret = assetManager.list(assetPath);
|
||||
listCache.put(assetPath, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private long getAssetSize(String assetPath) throws FileNotFoundException {
|
||||
if (assetPath.startsWith("/")) {
|
||||
assetPath = assetPath.substring(1);
|
||||
}
|
||||
lazyInitCaches();
|
||||
if (lengthCache != null) {
|
||||
Long ret = lengthCache.get(assetPath);
|
||||
if (ret == null) {
|
||||
throw new FileNotFoundException("Asset not found: " + assetPath);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
CordovaResourceApi.OpenForReadResult offr = null;
|
||||
try {
|
||||
offr = resourceApi.openForRead(nativeUriForFullPath(assetPath));
|
||||
long length = offr.length;
|
||||
if (length < 0) {
|
||||
// available() doesn't always yield the file size, but for assets it does.
|
||||
length = offr.inputStream.available();
|
||||
}
|
||||
return length;
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException("File not found: " + assetPath);
|
||||
} finally {
|
||||
if (offr != null) {
|
||||
try {
|
||||
offr.inputStream.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
|
||||
super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
|
||||
this.assetManager = assetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri toNativeUri(LocalFilesystemURL inputURL) {
|
||||
return nativeUriForFullPath(inputURL.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL toLocalUri(Uri inputURL) {
|
||||
if (!"file".equals(inputURL.getScheme())) {
|
||||
return null;
|
||||
}
|
||||
File f = new File(inputURL.getPath());
|
||||
// Removes and duplicate /s (e.g. file:///a//b/c)
|
||||
Uri resolvedUri = Uri.fromFile(f);
|
||||
String rootUriNoTrailingSlash = rootUri.getEncodedPath();
|
||||
rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
|
||||
if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
|
||||
return null;
|
||||
}
|
||||
String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
|
||||
// Strip leading slash
|
||||
if (!subPath.isEmpty()) {
|
||||
subPath = subPath.substring(1);
|
||||
}
|
||||
Uri.Builder b = new Uri.Builder()
|
||||
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
|
||||
.authority("localhost")
|
||||
.path(name);
|
||||
if (!subPath.isEmpty()) {
|
||||
b.appendEncodedPath(subPath);
|
||||
}
|
||||
if (isDirectory(subPath) || inputURL.getPath().endsWith("/")) {
|
||||
// Add trailing / for directories.
|
||||
b.appendEncodedPath("");
|
||||
}
|
||||
return LocalFilesystemURL.parse(b.build());
|
||||
}
|
||||
|
||||
private boolean isDirectory(String assetPath) {
|
||||
try {
|
||||
return listAssets(assetPath).length != 0;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
String pathNoSlashes = inputURL.path.substring(1);
|
||||
if (pathNoSlashes.endsWith("/")) {
|
||||
pathNoSlashes = pathNoSlashes.substring(0, pathNoSlashes.length() - 1);
|
||||
}
|
||||
|
||||
String[] files;
|
||||
try {
|
||||
files = listAssets(pathNoSlashes);
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
|
||||
for (int i = 0; i < files.length; ++i) {
|
||||
entries[i] = localUrlforFullPath(new File(inputURL.path, files[i]).getPath());
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
|
||||
String path, JSONObject options, boolean directory)
|
||||
throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
|
||||
if (options != null && options.optBoolean("create")) {
|
||||
throw new UnsupportedOperationException("Assets are read-only");
|
||||
}
|
||||
|
||||
// Check whether the supplied path is absolute or relative
|
||||
if (directory && !path.endsWith("/")) {
|
||||
path += "/";
|
||||
}
|
||||
|
||||
LocalFilesystemURL requestedURL;
|
||||
if (path.startsWith("/")) {
|
||||
requestedURL = localUrlforFullPath(normalizePath(path));
|
||||
} else {
|
||||
requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
|
||||
}
|
||||
|
||||
// Throws a FileNotFoundException if it doesn't exist.
|
||||
getFileMetadataForLocalURL(requestedURL);
|
||||
|
||||
boolean isDir = isDirectory(requestedURL.path);
|
||||
if (directory && !isDir) {
|
||||
throw new TypeMismatchException("path doesn't exist or is file");
|
||||
} else if (!directory && isDir) {
|
||||
throw new TypeMismatchException("path doesn't exist or is directory");
|
||||
}
|
||||
|
||||
// Return the directory
|
||||
return makeEntryForURL(requestedURL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
JSONObject metadata = new JSONObject();
|
||||
long size = inputURL.isDirectory ? 0 : getAssetSize(inputURL.path);
|
||||
try {
|
||||
metadata.put("size", size);
|
||||
metadata.put("type", inputURL.isDirectory ? "text/directory" : resourceApi.getMimeType(toNativeUri(inputURL)));
|
||||
metadata.put("name", new File(inputURL.path).getName());
|
||||
metadata.put("fullPath", inputURL.path);
|
||||
metadata.put("lastModifiedDate", 0);
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset, boolean isBinary) throws NoModificationAllowedException, IOException {
|
||||
throw new NoModificationAllowedException("Assets are read-only");
|
||||
}
|
||||
|
||||
@Override
|
||||
long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException, NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Assets are read-only");
|
||||
}
|
||||
|
||||
@Override
|
||||
String filesystemPathForURL(LocalFilesystemURL url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
LocalFilesystemURL URLforFilesystemPath(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Assets are read-only");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Assets are read-only");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,216 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.OpenableColumns;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import org.apache.cordova.CordovaResourceApi;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class ContentFilesystem extends Filesystem {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public ContentFilesystem(Context context, CordovaResourceApi resourceApi) {
|
||||
super(Uri.parse("content://"), "content", resourceApi);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri toNativeUri(LocalFilesystemURL inputURL) {
|
||||
String authorityAndPath = inputURL.uri.getEncodedPath().substring(this.name.length() + 2);
|
||||
if (authorityAndPath.length() < 2) {
|
||||
return null;
|
||||
}
|
||||
String ret = "content://" + authorityAndPath;
|
||||
String query = inputURL.uri.getEncodedQuery();
|
||||
if (query != null) {
|
||||
ret += '?' + query;
|
||||
}
|
||||
String frag = inputURL.uri.getEncodedFragment();
|
||||
if (frag != null) {
|
||||
ret += '#' + frag;
|
||||
}
|
||||
return Uri.parse(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL toLocalUri(Uri inputURL) {
|
||||
if (!"content".equals(inputURL.getScheme())) {
|
||||
return null;
|
||||
}
|
||||
String subPath = inputURL.getEncodedPath();
|
||||
if (subPath.length() > 0) {
|
||||
subPath = subPath.substring(1);
|
||||
}
|
||||
Uri.Builder b = new Uri.Builder()
|
||||
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
|
||||
.authority("localhost")
|
||||
.path(name)
|
||||
.appendPath(inputURL.getAuthority());
|
||||
if (subPath.length() > 0) {
|
||||
b.appendEncodedPath(subPath);
|
||||
}
|
||||
Uri localUri = b.encodedQuery(inputURL.getEncodedQuery())
|
||||
.encodedFragment(inputURL.getEncodedFragment())
|
||||
.build();
|
||||
return LocalFilesystemURL.parse(localUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
|
||||
String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
|
||||
throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL)
|
||||
throws NoModificationAllowedException {
|
||||
Uri contentUri = toNativeUri(inputURL);
|
||||
try {
|
||||
context.getContentResolver().delete(contentUri, null, null);
|
||||
} catch (UnsupportedOperationException t) {
|
||||
// Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator.
|
||||
// The ContentResolver applies only when the file was registered in the
|
||||
// first case, which is generally only the case with images.
|
||||
throw new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL)
|
||||
throws NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Cannot remove content url");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
long size = -1;
|
||||
long lastModified = 0;
|
||||
Uri nativeUri = toNativeUri(inputURL);
|
||||
String mimeType = resourceApi.getMimeType(nativeUri);
|
||||
Cursor cursor = openCursorForURL(nativeUri);
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
size = resourceSizeForCursor(cursor);
|
||||
Long modified = lastModifiedDateForCursor(cursor);
|
||||
if (modified != null)
|
||||
lastModified = modified.longValue();
|
||||
} else {
|
||||
// Some content providers don't support cursors at all!
|
||||
CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri);
|
||||
size = offr.length;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException();
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
JSONObject metadata = new JSONObject();
|
||||
try {
|
||||
metadata.put("size", size);
|
||||
metadata.put("type", mimeType);
|
||||
metadata.put("name", name);
|
||||
metadata.put("fullPath", inputURL.path);
|
||||
metadata.put("lastModifiedDate", lastModified);
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
|
||||
int offset, boolean isBinary) throws NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Couldn't write to file given its content URI");
|
||||
}
|
||||
@Override
|
||||
public long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
|
||||
throws NoModificationAllowedException {
|
||||
throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
|
||||
}
|
||||
|
||||
protected Cursor openCursorForURL(Uri nativeUri) {
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
try {
|
||||
return contentResolver.query(nativeUri, null, null, null, null);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Long resourceSizeForCursor(Cursor cursor) {
|
||||
int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
|
||||
if (columnIndex != -1) {
|
||||
String sizeStr = cursor.getString(columnIndex);
|
||||
if (sizeStr != null) {
|
||||
return Long.parseLong(sizeStr);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Long lastModifiedDateForCursor(Cursor cursor) {
|
||||
int columnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED);
|
||||
if (columnIndex == -1) {
|
||||
columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
|
||||
}
|
||||
if (columnIndex != -1) {
|
||||
String dateStr = cursor.getString(columnIndex);
|
||||
if (dateStr != null) {
|
||||
return Long.parseLong(dateStr);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filesystemPathForURL(LocalFilesystemURL url) {
|
||||
File f = resourceApi.mapUriToFile(toNativeUri(url));
|
||||
return f == null ? null : f.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL URLforFilesystemPath(String path) {
|
||||
// Returns null as we don't support reverse mapping back to content:// URLs
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This class provides file directory utilities.
|
||||
* All file operations are performed on the SD card.
|
||||
*
|
||||
* It is used by the FileUtils class.
|
||||
*/
|
||||
public class DirectoryManager {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String LOG_TAG = "DirectoryManager";
|
||||
|
||||
/**
|
||||
* Determine if a file or directory exists.
|
||||
* @param name The name of the file to check.
|
||||
* @return T=exists, F=not found
|
||||
*/
|
||||
public static boolean testFileExists(String name) {
|
||||
boolean status;
|
||||
|
||||
// If SD card exists
|
||||
if ((testSaveLocationExists()) && (!name.equals(""))) {
|
||||
File path = Environment.getExternalStorageDirectory();
|
||||
File newPath = constructFilePaths(path.toString(), name);
|
||||
status = newPath.exists();
|
||||
}
|
||||
// If no SD card
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the free space in external storage
|
||||
*
|
||||
* @return Size in KB or -1 if not available
|
||||
*/
|
||||
public static long getFreeExternalStorageSpace() {
|
||||
String status = Environment.getExternalStorageState();
|
||||
long freeSpaceInBytes = 0;
|
||||
|
||||
// Check if external storage exists
|
||||
if (status.equals(Environment.MEDIA_MOUNTED)) {
|
||||
freeSpaceInBytes = getFreeSpaceInBytes(Environment.getExternalStorageDirectory().getPath());
|
||||
} else {
|
||||
// If no external storage then return -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
return freeSpaceInBytes / 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a path return the number of free bytes in the filesystem containing the path.
|
||||
*
|
||||
* @param path to the file system
|
||||
* @return free space in bytes
|
||||
*/
|
||||
public static long getFreeSpaceInBytes(String path) {
|
||||
try {
|
||||
StatFs stat = new StatFs(path);
|
||||
long blockSize = stat.getBlockSize();
|
||||
long availableBlocks = stat.getAvailableBlocks();
|
||||
return availableBlocks * blockSize;
|
||||
} catch (IllegalArgumentException e) {
|
||||
// The path was invalid. Just return 0 free bytes.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if SD card exists.
|
||||
*
|
||||
* @return T=exists, F=not found
|
||||
*/
|
||||
public static boolean testSaveLocationExists() {
|
||||
String sDCardStatus = Environment.getExternalStorageState();
|
||||
boolean status;
|
||||
|
||||
// If SD card is mounted
|
||||
if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
|
||||
status = true;
|
||||
}
|
||||
|
||||
// If no SD card
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new file object from two file paths.
|
||||
*
|
||||
* @param file1 Base file path
|
||||
* @param file2 Remaining file path
|
||||
* @return File object
|
||||
*/
|
||||
private static File constructFilePaths (String file1, String file2) {
|
||||
File newPath;
|
||||
if (file2.startsWith(file1)) {
|
||||
newPath = new File(file2);
|
||||
}
|
||||
else {
|
||||
newPath = new File(file1 + "/" + file2);
|
||||
}
|
||||
return newPath;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova.file;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class EncodingException extends Exception {
|
||||
|
||||
public EncodingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova.file;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class FileExistsException extends Exception {
|
||||
|
||||
public FileExistsException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
1196
platforms/android/src/org/apache/cordova/file/FileUtils.java
Normal file
1196
platforms/android/src/org/apache/cordova/file/FileUtils.java
Normal file
File diff suppressed because it is too large
Load Diff
331
platforms/android/src/org/apache/cordova/file/Filesystem.java
Normal file
331
platforms/android/src/org/apache/cordova/file/Filesystem.java
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.cordova.CordovaResourceApi;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public abstract class Filesystem {
|
||||
|
||||
protected final Uri rootUri;
|
||||
protected final CordovaResourceApi resourceApi;
|
||||
public final String name;
|
||||
private JSONObject rootEntry;
|
||||
|
||||
public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi) {
|
||||
this.rootUri = rootUri;
|
||||
this.name = name;
|
||||
this.resourceApi = resourceApi;
|
||||
}
|
||||
|
||||
public interface ReadFileCallback {
|
||||
public void handleData(InputStream inputStream, String contentType) throws IOException;
|
||||
}
|
||||
|
||||
public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
|
||||
try {
|
||||
String path = inputURL.path;
|
||||
int end = path.endsWith("/") ? 1 : 0;
|
||||
String[] parts = path.substring(0, path.length() - end).split("/+");
|
||||
String fileName = parts[parts.length - 1];
|
||||
|
||||
JSONObject entry = new JSONObject();
|
||||
entry.put("isFile", !inputURL.isDirectory);
|
||||
entry.put("isDirectory", inputURL.isDirectory);
|
||||
entry.put("name", fileName);
|
||||
entry.put("fullPath", path);
|
||||
// The file system can't be specified, as it would lead to an infinite loop,
|
||||
// but the filesystem name can be.
|
||||
entry.put("filesystemName", inputURL.fsName);
|
||||
// Backwards compatibility
|
||||
entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);
|
||||
|
||||
String nativeUrlStr = nativeURL.toString();
|
||||
if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
|
||||
nativeUrlStr += "/";
|
||||
}
|
||||
entry.put("nativeURL", nativeUrlStr);
|
||||
return entry;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
|
||||
Uri nativeUri = toNativeUri(inputURL);
|
||||
return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
|
||||
}
|
||||
|
||||
public JSONObject makeEntryForNativeUri(Uri nativeUri) {
|
||||
LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
|
||||
return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
|
||||
}
|
||||
|
||||
public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
|
||||
return makeEntryForURL(inputURL);
|
||||
}
|
||||
|
||||
public JSONObject makeEntryForFile(File file) {
|
||||
return makeEntryForNativeUri(Uri.fromFile(file));
|
||||
}
|
||||
|
||||
abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
|
||||
JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
|
||||
|
||||
abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
|
||||
|
||||
abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
|
||||
|
||||
abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;
|
||||
|
||||
public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
LocalFilesystemURL[] children = listChildren(inputURL);
|
||||
JSONArray entries = new JSONArray();
|
||||
if (children != null) {
|
||||
for (LocalFilesystemURL url : children) {
|
||||
entries.put(makeEntryForURL(url));
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
|
||||
|
||||
public Uri getRootUri() {
|
||||
return rootUri;
|
||||
}
|
||||
|
||||
public boolean exists(LocalFilesystemURL inputURL) {
|
||||
try {
|
||||
getFileMetadataForLocalURL(inputURL);
|
||||
} catch (FileNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Uri nativeUriForFullPath(String fullPath) {
|
||||
Uri ret = null;
|
||||
if (fullPath != null) {
|
||||
String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
|
||||
if (encodedPath.startsWith("/")) {
|
||||
encodedPath = encodedPath.substring(1);
|
||||
}
|
||||
ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public LocalFilesystemURL localUrlforFullPath(String fullPath) {
|
||||
Uri nativeUri = nativeUriForFullPath(fullPath);
|
||||
if (nativeUri != null) {
|
||||
return toLocalUri(nativeUri);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple repeated //s, and collapses processes ../s.
|
||||
*/
|
||||
protected static String normalizePath(String rawPath) {
|
||||
// If this is an absolute path, trim the leading "/" and replace it later
|
||||
boolean isAbsolutePath = rawPath.startsWith("/");
|
||||
if (isAbsolutePath) {
|
||||
rawPath = rawPath.replaceFirst("/+", "");
|
||||
}
|
||||
ArrayList<String> components = new ArrayList<String>(Arrays.asList(rawPath.split("/+")));
|
||||
for (int index = 0; index < components.size(); ++index) {
|
||||
if (components.get(index).equals("..")) {
|
||||
components.remove(index);
|
||||
if (index > 0) {
|
||||
components.remove(index-1);
|
||||
--index;
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder normalizedPath = new StringBuilder();
|
||||
for(String component: components) {
|
||||
normalizedPath.append("/");
|
||||
normalizedPath.append(component);
|
||||
}
|
||||
if (isAbsolutePath) {
|
||||
return normalizedPath.toString();
|
||||
} else {
|
||||
return normalizedPath.toString().substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the free space in bytes available on this filesystem.
|
||||
* Subclasses may override this method to return nonzero free space.
|
||||
*/
|
||||
public long getFreeSpaceInBytes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
|
||||
public abstract LocalFilesystemURL toLocalUri(Uri inputURL);
|
||||
|
||||
public JSONObject getRootEntry() {
|
||||
if (rootEntry == null) {
|
||||
rootEntry = makeEntryForNativeUri(rootUri);
|
||||
}
|
||||
return rootEntry;
|
||||
}
|
||||
|
||||
public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
|
||||
Uri parentUri = inputURL.uri;
|
||||
String parentPath = new File(inputURL.uri.getPath()).getParent();
|
||||
if (!"/".equals(parentPath)) {
|
||||
parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
|
||||
}
|
||||
return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
|
||||
}
|
||||
|
||||
protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
|
||||
// I know this looks weird but it is to work around a JSON bug.
|
||||
if ("null".equals(newName) || "".equals(newName)) {
|
||||
newName = srcURL.uri.getLastPathSegment();;
|
||||
}
|
||||
|
||||
String newDest = destURL.uri.toString();
|
||||
if (newDest.endsWith("/")) {
|
||||
newDest = newDest + newName;
|
||||
} else {
|
||||
newDest = newDest + "/" + newName;
|
||||
}
|
||||
if (isDirectory) {
|
||||
newDest += '/';
|
||||
}
|
||||
return LocalFilesystemURL.parse(newDest);
|
||||
}
|
||||
|
||||
/* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
|
||||
* the destination URL on this filesystem, optionally with a new filename.
|
||||
* If move is true, then this method should either perform an atomic move operation
|
||||
* or remove the source file when finished.
|
||||
*/
|
||||
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
|
||||
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
|
||||
// First, check to see that we can do it
|
||||
if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
|
||||
throw new NoModificationAllowedException("Cannot move file at source URL");
|
||||
}
|
||||
final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
|
||||
|
||||
Uri srcNativeUri = srcFs.toNativeUri(srcURL);
|
||||
|
||||
CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = getOutputStreamForURL(destination);
|
||||
} catch (IOException e) {
|
||||
ofrr.inputStream.close();
|
||||
throw e;
|
||||
}
|
||||
// Closes streams.
|
||||
resourceApi.copyResource(ofrr, os);
|
||||
|
||||
if (move) {
|
||||
srcFs.removeFileAtLocalURL(srcURL);
|
||||
}
|
||||
return getEntryForLocalURL(destination);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
|
||||
return resourceApi.openOutputStream(toNativeUri(inputURL));
|
||||
}
|
||||
|
||||
public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
|
||||
ReadFileCallback readFileCallback) throws IOException {
|
||||
CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
|
||||
if (end < 0) {
|
||||
end = ofrr.length;
|
||||
}
|
||||
long numBytesToRead = end - start;
|
||||
try {
|
||||
if (start > 0) {
|
||||
ofrr.inputStream.skip(start);
|
||||
}
|
||||
InputStream inputStream = ofrr.inputStream;
|
||||
if (end < ofrr.length) {
|
||||
inputStream = new LimitedInputStream(inputStream, numBytesToRead);
|
||||
}
|
||||
readFileCallback.handleData(inputStream, ofrr.mimeType);
|
||||
} finally {
|
||||
ofrr.inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
|
||||
boolean isBinary) throws NoModificationAllowedException, IOException;
|
||||
|
||||
abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
|
||||
throws IOException, NoModificationAllowedException;
|
||||
|
||||
// This method should return null if filesystem urls cannot be mapped to paths
|
||||
abstract String filesystemPathForURL(LocalFilesystemURL url);
|
||||
|
||||
abstract LocalFilesystemURL URLforFilesystemPath(String path);
|
||||
|
||||
abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
|
||||
|
||||
protected class LimitedInputStream extends FilterInputStream {
|
||||
long numBytesToRead;
|
||||
public LimitedInputStream(InputStream in, long numBytesToRead) {
|
||||
super(in);
|
||||
this.numBytesToRead = numBytesToRead;
|
||||
}
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (numBytesToRead <= 0) {
|
||||
return -1;
|
||||
}
|
||||
numBytesToRead--;
|
||||
return in.read();
|
||||
}
|
||||
@Override
|
||||
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
|
||||
if (numBytesToRead <= 0) {
|
||||
return -1;
|
||||
}
|
||||
int bytesToRead = byteCount;
|
||||
if (byteCount > numBytesToRead) {
|
||||
bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
|
||||
}
|
||||
int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
|
||||
numBytesToRead -= numBytesRead;
|
||||
return numBytesRead;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.cordova.file;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class InvalidModificationException extends Exception {
|
||||
|
||||
public InvalidModificationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,510 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileChannel;
|
||||
import org.apache.cordova.CordovaResourceApi;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.util.Base64;
|
||||
import android.net.Uri;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class LocalFilesystem extends Filesystem {
|
||||
private final Context context;
|
||||
|
||||
public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
|
||||
super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public String filesystemPathForFullPath(String fullPath) {
|
||||
return new File(rootUri.getPath(), fullPath).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filesystemPathForURL(LocalFilesystemURL url) {
|
||||
return filesystemPathForFullPath(url.path);
|
||||
}
|
||||
|
||||
private String fullPathForFilesystemPath(String absolutePath) {
|
||||
if (absolutePath != null && absolutePath.startsWith(rootUri.getPath())) {
|
||||
return absolutePath.substring(rootUri.getPath().length() - 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri toNativeUri(LocalFilesystemURL inputURL) {
|
||||
return nativeUriForFullPath(inputURL.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL toLocalUri(Uri inputURL) {
|
||||
if (!"file".equals(inputURL.getScheme())) {
|
||||
return null;
|
||||
}
|
||||
File f = new File(inputURL.getPath());
|
||||
// Removes and duplicate /s (e.g. file:///a//b/c)
|
||||
Uri resolvedUri = Uri.fromFile(f);
|
||||
String rootUriNoTrailingSlash = rootUri.getEncodedPath();
|
||||
rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
|
||||
if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
|
||||
return null;
|
||||
}
|
||||
String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
|
||||
// Strip leading slash
|
||||
if (!subPath.isEmpty()) {
|
||||
subPath = subPath.substring(1);
|
||||
}
|
||||
Uri.Builder b = new Uri.Builder()
|
||||
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
|
||||
.authority("localhost")
|
||||
.path(name);
|
||||
if (!subPath.isEmpty()) {
|
||||
b.appendEncodedPath(subPath);
|
||||
}
|
||||
if (f.isDirectory()) {
|
||||
// Add trailing / for directories.
|
||||
b.appendEncodedPath("");
|
||||
}
|
||||
return LocalFilesystemURL.parse(b.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL URLforFilesystemPath(String path) {
|
||||
return localUrlforFullPath(fullPathForFilesystemPath(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
|
||||
String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
|
||||
boolean create = false;
|
||||
boolean exclusive = false;
|
||||
|
||||
if (options != null) {
|
||||
create = options.optBoolean("create");
|
||||
if (create) {
|
||||
exclusive = options.optBoolean("exclusive");
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a ":" character in the file to line up with BB and iOS
|
||||
if (path.contains(":")) {
|
||||
throw new EncodingException("This path has an invalid \":\" in it.");
|
||||
}
|
||||
|
||||
LocalFilesystemURL requestedURL;
|
||||
|
||||
// Check whether the supplied path is absolute or relative
|
||||
if (directory && !path.endsWith("/")) {
|
||||
path += "/";
|
||||
}
|
||||
if (path.startsWith("/")) {
|
||||
requestedURL = localUrlforFullPath(normalizePath(path));
|
||||
} else {
|
||||
requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
|
||||
}
|
||||
|
||||
File fp = new File(this.filesystemPathForURL(requestedURL));
|
||||
|
||||
if (create) {
|
||||
if (exclusive && fp.exists()) {
|
||||
throw new FileExistsException("create/exclusive fails");
|
||||
}
|
||||
if (directory) {
|
||||
fp.mkdir();
|
||||
} else {
|
||||
fp.createNewFile();
|
||||
}
|
||||
if (!fp.exists()) {
|
||||
throw new FileExistsException("create fails");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!fp.exists()) {
|
||||
throw new FileNotFoundException("path does not exist");
|
||||
}
|
||||
if (directory) {
|
||||
if (fp.isFile()) {
|
||||
throw new TypeMismatchException("path doesn't exist or is file");
|
||||
}
|
||||
} else {
|
||||
if (fp.isDirectory()) {
|
||||
throw new TypeMismatchException("path doesn't exist or is directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the directory
|
||||
return makeEntryForURL(requestedURL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException {
|
||||
|
||||
File fp = new File(filesystemPathForURL(inputURL));
|
||||
|
||||
// You can't delete a directory that is not empty
|
||||
if (fp.isDirectory() && fp.list().length > 0) {
|
||||
throw new InvalidModificationException("You can't delete a directory that is not empty.");
|
||||
}
|
||||
|
||||
return fp.delete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(LocalFilesystemURL inputURL) {
|
||||
File fp = new File(filesystemPathForURL(inputURL));
|
||||
return fp.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFreeSpaceInBytes() {
|
||||
return DirectoryManager.getFreeSpaceInBytes(rootUri.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException {
|
||||
File directory = new File(filesystemPathForURL(inputURL));
|
||||
return removeDirRecursively(directory);
|
||||
}
|
||||
|
||||
protected boolean removeDirRecursively(File directory) throws FileExistsException {
|
||||
if (directory.isDirectory()) {
|
||||
for (File file : directory.listFiles()) {
|
||||
removeDirRecursively(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (!directory.delete()) {
|
||||
throw new FileExistsException("could not delete: " + directory.getName());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
File fp = new File(filesystemPathForURL(inputURL));
|
||||
|
||||
if (!fp.exists()) {
|
||||
// The directory we are listing doesn't exist so we should fail.
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
File[] files = fp.listFiles();
|
||||
if (files == null) {
|
||||
// inputURL is a directory
|
||||
return null;
|
||||
}
|
||||
LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
entries[i] = URLforFilesystemPath(files[i].getPath());
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
|
||||
File file = new File(filesystemPathForURL(inputURL));
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
|
||||
}
|
||||
|
||||
JSONObject metadata = new JSONObject();
|
||||
try {
|
||||
// Ensure that directories report a size of 0
|
||||
metadata.put("size", file.isDirectory() ? 0 : file.length());
|
||||
metadata.put("type", resourceApi.getMimeType(Uri.fromFile(file)));
|
||||
metadata.put("name", file.getName());
|
||||
metadata.put("fullPath", inputURL.path);
|
||||
metadata.put("lastModifiedDate", file.lastModified());
|
||||
} catch (JSONException e) {
|
||||
return null;
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
|
||||
if (move) {
|
||||
String realSrcPath = srcFs.filesystemPathForURL(srcURL);
|
||||
if (realSrcPath != null) {
|
||||
File srcFile = new File(realSrcPath);
|
||||
if (srcFile.renameTo(destFile)) {
|
||||
return;
|
||||
}
|
||||
// Trying to rename the file failed. Possibly because we moved across file system on the device.
|
||||
}
|
||||
}
|
||||
|
||||
CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
|
||||
copyResource(offr, new FileOutputStream(destFile));
|
||||
|
||||
if (move) {
|
||||
srcFs.removeFileAtLocalURL(srcURL);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
|
||||
if (move) {
|
||||
String realSrcPath = srcFs.filesystemPathForURL(srcURL);
|
||||
if (realSrcPath != null) {
|
||||
File srcDir = new File(realSrcPath);
|
||||
// If the destination directory already exists and is empty then delete it. This is according to spec.
|
||||
if (dstDir.exists()) {
|
||||
if (dstDir.list().length > 0) {
|
||||
throw new InvalidModificationException("directory is not empty");
|
||||
}
|
||||
dstDir.delete();
|
||||
}
|
||||
// Try to rename the directory
|
||||
if (srcDir.renameTo(dstDir)) {
|
||||
return;
|
||||
}
|
||||
// Trying to rename the file failed. Possibly because we moved across file system on the device.
|
||||
}
|
||||
}
|
||||
|
||||
if (dstDir.exists()) {
|
||||
if (dstDir.list().length > 0) {
|
||||
throw new InvalidModificationException("directory is not empty");
|
||||
}
|
||||
} else {
|
||||
if (!dstDir.mkdir()) {
|
||||
// If we can't create the directory then fail
|
||||
throw new NoModificationAllowedException("Couldn't create the destination directory");
|
||||
}
|
||||
}
|
||||
|
||||
LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
|
||||
for (LocalFilesystemURL childLocalUrl : children) {
|
||||
File target = new File(dstDir, new File(childLocalUrl.path).getName());
|
||||
if (childLocalUrl.isDirectory) {
|
||||
copyDirectory(srcFs, childLocalUrl, target, false);
|
||||
} else {
|
||||
copyFile(srcFs, childLocalUrl, target, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (move) {
|
||||
srcFs.recursiveRemoveFileAtLocalURL(srcURL);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
|
||||
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
|
||||
|
||||
// Check to see if the destination directory exists
|
||||
String newParent = this.filesystemPathForURL(destURL);
|
||||
File destinationDir = new File(newParent);
|
||||
if (!destinationDir.exists()) {
|
||||
// The destination does not exist so we should fail.
|
||||
throw new FileNotFoundException("The source does not exist");
|
||||
}
|
||||
|
||||
// Figure out where we should be copying to
|
||||
final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
|
||||
|
||||
Uri dstNativeUri = toNativeUri(destinationURL);
|
||||
Uri srcNativeUri = srcFs.toNativeUri(srcURL);
|
||||
// Check to see if source and destination are the same file
|
||||
if (dstNativeUri.equals(srcNativeUri)) {
|
||||
throw new InvalidModificationException("Can't copy onto itself");
|
||||
}
|
||||
|
||||
if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
|
||||
throw new InvalidModificationException("Source URL is read-only (cannot move)");
|
||||
}
|
||||
|
||||
File destFile = new File(dstNativeUri.getPath());
|
||||
if (destFile.exists()) {
|
||||
if (!srcURL.isDirectory && destFile.isDirectory()) {
|
||||
throw new InvalidModificationException("Can't copy/move a file to an existing directory");
|
||||
} else if (srcURL.isDirectory && destFile.isFile()) {
|
||||
throw new InvalidModificationException("Can't copy/move a directory to an existing file");
|
||||
}
|
||||
}
|
||||
|
||||
if (srcURL.isDirectory) {
|
||||
// E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
|
||||
if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
|
||||
throw new InvalidModificationException("Can't copy directory into itself");
|
||||
}
|
||||
copyDirectory(srcFs, srcURL, destFile, move);
|
||||
} else {
|
||||
copyFile(srcFs, srcURL, destFile, move);
|
||||
}
|
||||
return makeEntryForURL(destinationURL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
|
||||
int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
|
||||
|
||||
boolean append = false;
|
||||
if (offset > 0) {
|
||||
this.truncateFileAtURL(inputURL, offset);
|
||||
append = true;
|
||||
}
|
||||
|
||||
byte[] rawData;
|
||||
if (isBinary) {
|
||||
rawData = Base64.decode(data, Base64.DEFAULT);
|
||||
} else {
|
||||
rawData = data.getBytes();
|
||||
}
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
|
||||
try
|
||||
{
|
||||
byte buff[] = new byte[rawData.length];
|
||||
String absolutePath = filesystemPathForURL(inputURL);
|
||||
FileOutputStream out = new FileOutputStream(absolutePath, append);
|
||||
try {
|
||||
in.read(buff, 0, buff.length);
|
||||
out.write(buff, 0, rawData.length);
|
||||
out.flush();
|
||||
} finally {
|
||||
// Always close the output
|
||||
out.close();
|
||||
}
|
||||
if (isPublicDirectory(absolutePath)) {
|
||||
broadcastNewFile(Uri.fromFile(new File(absolutePath)));
|
||||
}
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
// This is a bug in the Android implementation of the Java Stack
|
||||
NoModificationAllowedException realException = new NoModificationAllowedException(inputURL.toString());
|
||||
throw realException;
|
||||
}
|
||||
|
||||
return rawData.length;
|
||||
}
|
||||
|
||||
private boolean isPublicDirectory(String absolutePath) {
|
||||
// TODO: should expose a way to scan app's private files (maybe via a flag).
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// Lollipop has a bug where SD cards are null.
|
||||
for (File f : context.getExternalMediaDirs()) {
|
||||
if(f != null && absolutePath.startsWith(f.getAbsolutePath())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
return absolutePath.startsWith(extPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send broadcast of new file so files appear over MTP
|
||||
*/
|
||||
private void broadcastNewFile(Uri nativeUri) {
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, nativeUri);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException {
|
||||
File file = new File(filesystemPathForURL(inputURL));
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
|
||||
}
|
||||
|
||||
RandomAccessFile raf = new RandomAccessFile(filesystemPathForURL(inputURL), "rw");
|
||||
try {
|
||||
if (raf.length() >= size) {
|
||||
FileChannel channel = raf.getChannel();
|
||||
channel.truncate(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
return raf.length();
|
||||
} finally {
|
||||
raf.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
|
||||
String path = filesystemPathForURL(inputURL);
|
||||
File file = new File(path);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
// This is a copy & paste from CordovaResource API that is required since CordovaResourceApi
|
||||
// has a bug pre-4.0.0.
|
||||
// TODO: Once cordova-android@4.0.0 is released, delete this copy and make the plugin depend on
|
||||
// 4.0.0 with an engine tag.
|
||||
private static void copyResource(CordovaResourceApi.OpenForReadResult input, OutputStream outputStream) throws IOException {
|
||||
try {
|
||||
InputStream inputStream = input.inputStream;
|
||||
if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
|
||||
FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
|
||||
FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
|
||||
long offset = 0;
|
||||
long length = input.length;
|
||||
if (input.assetFd != null) {
|
||||
offset = input.assetFd.getStartOffset();
|
||||
}
|
||||
// transferFrom()'s 2nd arg is a relative position. Need to set the absolute
|
||||
// position first.
|
||||
inChannel.position(offset);
|
||||
outChannel.transferFrom(inChannel, 0, length);
|
||||
} else {
|
||||
final int BUFFER_SIZE = 8192;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
for (;;) {
|
||||
int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
|
||||
|
||||
if (bytesRead <= 0) {
|
||||
break;
|
||||
}
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
input.inputStream.close();
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
public class LocalFilesystemURL {
|
||||
|
||||
public static final String FILESYSTEM_PROTOCOL = "cdvfile";
|
||||
|
||||
public final Uri uri;
|
||||
public final String fsName;
|
||||
public final String path;
|
||||
public final boolean isDirectory;
|
||||
|
||||
private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) {
|
||||
this.uri = uri;
|
||||
this.fsName = fsName;
|
||||
this.path = fsPath;
|
||||
this.isDirectory = isDirectory;
|
||||
}
|
||||
|
||||
public static LocalFilesystemURL parse(Uri uri) {
|
||||
if (!FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
|
||||
return null;
|
||||
}
|
||||
String path = uri.getPath();
|
||||
if (path.length() < 1) {
|
||||
return null;
|
||||
}
|
||||
int firstSlashIdx = path.indexOf('/', 1);
|
||||
if (firstSlashIdx < 0) {
|
||||
return null;
|
||||
}
|
||||
String fsName = path.substring(1, firstSlashIdx);
|
||||
path = path.substring(firstSlashIdx);
|
||||
boolean isDirectory = path.charAt(path.length() - 1) == '/';
|
||||
return new LocalFilesystemURL(uri, fsName, path, isDirectory);
|
||||
}
|
||||
|
||||
public static LocalFilesystemURL parse(String uri) {
|
||||
return parse(Uri.parse(uri));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return uri.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova.file;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class NoModificationAllowedException extends Exception {
|
||||
|
||||
public NoModificationAllowedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.file;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
|
||||
/**
|
||||
* Holds pending runtime permission requests
|
||||
*/
|
||||
class PendingRequests {
|
||||
private int currentReqId = 0;
|
||||
private SparseArray<Request> requests = new SparseArray<Request>();
|
||||
|
||||
/**
|
||||
* Creates a request and adds it to the array of pending requests. Each created request gets a
|
||||
* unique result code for use with requestPermission()
|
||||
* @param rawArgs The raw arguments passed to the plugin
|
||||
* @param action The action this request corresponds to (get file, etc.)
|
||||
* @param callbackContext The CallbackContext for this plugin call
|
||||
* @return The request code that can be used to retrieve the Request object
|
||||
*/
|
||||
public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext) {
|
||||
Request req = new Request(rawArgs, action, callbackContext);
|
||||
requests.put(req.requestCode, req);
|
||||
return req.requestCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the request corresponding to this request code and removes it from the pending requests
|
||||
* @param requestCode The request code for the desired request
|
||||
* @return The request corresponding to the given request code or null if such a
|
||||
* request is not found
|
||||
*/
|
||||
public synchronized Request getAndRemove(int requestCode) {
|
||||
Request result = requests.get(requestCode);
|
||||
requests.remove(requestCode);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the options and CallbackContext for a call made to the plugin.
|
||||
*/
|
||||
public class Request {
|
||||
|
||||
// Unique int used to identify this request in any Android permission callback
|
||||
private int requestCode;
|
||||
|
||||
// Action to be performed after permission request result
|
||||
private int action;
|
||||
|
||||
// Raw arguments passed to plugin
|
||||
private String rawArgs;
|
||||
|
||||
// The callback context for this plugin request
|
||||
private CallbackContext callbackContext;
|
||||
|
||||
private Request(String rawArgs, int action, CallbackContext callbackContext) {
|
||||
this.rawArgs = rawArgs;
|
||||
this.action = action;
|
||||
this.callbackContext = callbackContext;
|
||||
this.requestCode = currentReqId ++;
|
||||
}
|
||||
|
||||
public int getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
||||
public String getRawArgs() {
|
||||
return rawArgs;
|
||||
}
|
||||
|
||||
public CallbackContext getCallbackContext() {
|
||||
return callbackContext;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.cordova.file;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class TypeMismatchException extends Exception {
|
||||
|
||||
public TypeMismatchException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
#import "CDVFile.h"
|
||||
|
||||
extern NSString* const kCDVAssetsLibraryPrefix;
|
||||
extern NSString* const kCDVAssetsLibraryScheme;
|
||||
|
||||
@interface CDVAssetLibraryFilesystem : NSObject<CDVFileSystem> {
|
||||
}
|
||||
|
||||
- (id) initWithName:(NSString *)name;
|
||||
|
||||
@end
|
@ -0,0 +1,253 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
#import "CDVFile.h"
|
||||
#import "CDVAssetLibraryFilesystem.h"
|
||||
#import <Cordova/CDV.h>
|
||||
#import <AssetsLibrary/ALAsset.h>
|
||||
#import <AssetsLibrary/ALAssetRepresentation.h>
|
||||
#import <AssetsLibrary/ALAssetsLibrary.h>
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
|
||||
NSString* const kCDVAssetsLibraryPrefix = @"assets-library://";
|
||||
NSString* const kCDVAssetsLibraryScheme = @"assets-library";
|
||||
|
||||
@implementation CDVAssetLibraryFilesystem
|
||||
@synthesize name=_name, urlTransformer;
|
||||
|
||||
|
||||
/*
|
||||
The CDVAssetLibraryFilesystem works with resources which are identified
|
||||
by iOS as
|
||||
asset-library://<path>
|
||||
and represents them internally as URLs of the form
|
||||
cdvfile://localhost/assets-library/<path>
|
||||
*/
|
||||
|
||||
- (NSURL *)assetLibraryURLForLocalURL:(CDVFilesystemURL *)url
|
||||
{
|
||||
if ([url.url.scheme isEqualToString:kCDVFilesystemURLPrefix]) {
|
||||
NSString *path = [[url.url absoluteString] substringFromIndex:[@"cdvfile://localhost/assets-library" length]];
|
||||
return [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@", path]];
|
||||
}
|
||||
return url.url;
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
|
||||
{
|
||||
NSDictionary* entry = [self makeEntryForLocalURL:url];
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
|
||||
}
|
||||
|
||||
- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
|
||||
return [self makeEntryForPath:url.fullPath isDirectory:NO];
|
||||
}
|
||||
|
||||
- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
|
||||
{
|
||||
NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
|
||||
NSString* lastPart = [fullPath lastPathComponent];
|
||||
if (isDir && ![fullPath hasSuffix:@"/"]) {
|
||||
fullPath = [fullPath stringByAppendingString:@"/"];
|
||||
}
|
||||
[dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"];
|
||||
[dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"];
|
||||
[dirEntry setObject:fullPath forKey:@"fullPath"];
|
||||
[dirEntry setObject:lastPart forKey:@"name"];
|
||||
[dirEntry setObject:self.name forKey: @"filesystemName"];
|
||||
|
||||
NSURL* nativeURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@",fullPath]];
|
||||
if (self.urlTransformer) {
|
||||
nativeURL = self.urlTransformer(nativeURL);
|
||||
}
|
||||
dirEntry[@"nativeURL"] = [nativeURL absoluteString];
|
||||
|
||||
return dirEntry;
|
||||
}
|
||||
|
||||
/* helper function to get the mimeType from the file extension
|
||||
* IN:
|
||||
* NSString* fullPath - filename (may include path)
|
||||
* OUT:
|
||||
* NSString* the mime type as type/subtype. nil if not able to determine
|
||||
*/
|
||||
+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
|
||||
{
|
||||
NSString* mimeType = nil;
|
||||
|
||||
if (fullPath) {
|
||||
CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
|
||||
if (typeId) {
|
||||
mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
|
||||
if (!mimeType) {
|
||||
// special case for m4a
|
||||
if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
|
||||
mimeType = @"audio/mp4";
|
||||
} else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
|
||||
mimeType = @"audio/wav";
|
||||
} else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
|
||||
mimeType = @"text/css";
|
||||
}
|
||||
}
|
||||
CFRelease(typeId);
|
||||
}
|
||||
}
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
- (id)initWithName:(NSString *)name
|
||||
{
|
||||
if (self) {
|
||||
self.name = name;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
|
||||
{
|
||||
// return unsupported result for assets-library URLs
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."];
|
||||
}
|
||||
|
||||
- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
// we don't (yet?) support getting the parent of an asset
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR];
|
||||
}
|
||||
|
||||
- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
|
||||
{
|
||||
// setMetadata doesn't make sense for asset library files
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
// return error for assets-library URLs
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
// return error for assets-library URLs
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
// return unsupported result for assets-library URLs
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
|
||||
{
|
||||
// assets-library files can't be truncated
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
|
||||
{
|
||||
// text can't be written into assets-library files
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
|
||||
}
|
||||
|
||||
- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
|
||||
{
|
||||
// Copying to an assets library file is not doable, since we can't write it.
|
||||
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
|
||||
callback(result);
|
||||
}
|
||||
|
||||
- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
|
||||
{
|
||||
NSString *path = nil;
|
||||
if ([[url.url scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
|
||||
path = [url.url path];
|
||||
} else {
|
||||
path = url.fullPath;
|
||||
}
|
||||
if ([path hasSuffix:@"/"]) {
|
||||
path = [path substringToIndex:([path length]-1)];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
|
||||
{
|
||||
ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
|
||||
if (asset) {
|
||||
// We have the asset! Get the data and send it off.
|
||||
ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
|
||||
NSUInteger size = (end > start) ? (end - start) : [assetRepresentation size];
|
||||
Byte* buffer = (Byte*)malloc(size);
|
||||
NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:start length:size error:nil];
|
||||
NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
|
||||
NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
|
||||
|
||||
callback(data, MIMEType, NO_ERROR);
|
||||
} else {
|
||||
callback(nil, nil, NOT_FOUND_ERR);
|
||||
}
|
||||
};
|
||||
|
||||
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
|
||||
// Retrieving the asset failed for some reason. Send the appropriate error.
|
||||
NSLog(@"Error: %@", error);
|
||||
callback(nil, nil, SECURITY_ERR);
|
||||
};
|
||||
|
||||
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
|
||||
[assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
|
||||
}
|
||||
|
||||
- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
|
||||
{
|
||||
// In this case, we need to use an asynchronous method to retrieve the file.
|
||||
// Because of this, we can't just assign to `result` and send it at the end of the method.
|
||||
// Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
|
||||
ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
|
||||
if (asset) {
|
||||
// We have the asset! Populate the dictionary and send it off.
|
||||
NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
|
||||
ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
|
||||
[fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[assetRepresentation size]] forKey:@"size"];
|
||||
[fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
|
||||
NSString* filename = [assetRepresentation filename];
|
||||
[fileInfo setObject:filename forKey:@"name"];
|
||||
[fileInfo setObject:[CDVAssetLibraryFilesystem getMimeTypeFromPath:filename] forKey:@"type"];
|
||||
NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate];
|
||||
NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000];
|
||||
[fileInfo setObject:msDate forKey:@"lastModifiedDate"];
|
||||
|
||||
callback([CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]);
|
||||
} else {
|
||||
// We couldn't find the asset. Send the appropriate error.
|
||||
callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]);
|
||||
}
|
||||
};
|
||||
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
|
||||
// Retrieving the asset failed for some reason. Send the appropriate error.
|
||||
callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]);
|
||||
};
|
||||
|
||||
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
|
||||
[assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
|
||||
return;
|
||||
}
|
||||
@end
|
157
platforms/ios/Sensortoy/Plugins/cordova-plugin-file/CDVFile.h
Normal file
157
platforms/ios/Sensortoy/Plugins/cordova-plugin-file/CDVFile.h
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cordova/CDVPlugin.h>
|
||||
|
||||
NSString* const kCDVAssetsLibraryPrefix;
|
||||
NSString* const kCDVFilesystemURLPrefix;
|
||||
|
||||
enum CDVFileError {
|
||||
NO_ERROR = 0,
|
||||
NOT_FOUND_ERR = 1,
|
||||
SECURITY_ERR = 2,
|
||||
ABORT_ERR = 3,
|
||||
NOT_READABLE_ERR = 4,
|
||||
ENCODING_ERR = 5,
|
||||
NO_MODIFICATION_ALLOWED_ERR = 6,
|
||||
INVALID_STATE_ERR = 7,
|
||||
SYNTAX_ERR = 8,
|
||||
INVALID_MODIFICATION_ERR = 9,
|
||||
QUOTA_EXCEEDED_ERR = 10,
|
||||
TYPE_MISMATCH_ERR = 11,
|
||||
PATH_EXISTS_ERR = 12
|
||||
};
|
||||
typedef int CDVFileError;
|
||||
|
||||
@interface CDVFilesystemURL : NSObject {
|
||||
NSURL *_url;
|
||||
NSString *_fileSystemName;
|
||||
NSString *_fullPath;
|
||||
}
|
||||
|
||||
- (id) initWithString:(NSString*)strURL;
|
||||
- (id) initWithURL:(NSURL*)URL;
|
||||
+ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL;
|
||||
+ (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL;
|
||||
|
||||
- (NSString *)absoluteURL;
|
||||
|
||||
@property (atomic) NSURL *url;
|
||||
@property (atomic) NSString *fileSystemName;
|
||||
@property (atomic) NSString *fullPath;
|
||||
|
||||
@end
|
||||
|
||||
@interface CDVFilesystemURLProtocol : NSURLProtocol
|
||||
@end
|
||||
|
||||
@protocol CDVFileSystem
|
||||
- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url;
|
||||
- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options;
|
||||
- (CDVPluginResult *)getParentForURL:(CDVFilesystemURL *)localURI;
|
||||
- (CDVPluginResult *)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options;
|
||||
- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI;
|
||||
- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI;
|
||||
- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI;
|
||||
- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos;
|
||||
- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend;
|
||||
- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback;
|
||||
- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback;
|
||||
- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback;
|
||||
|
||||
- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url;
|
||||
- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir;
|
||||
|
||||
@property (nonatomic,strong) NSString *name;
|
||||
@property (nonatomic, copy) NSURL*(^urlTransformer)(NSURL*);
|
||||
|
||||
@optional
|
||||
- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURI;
|
||||
- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path;
|
||||
|
||||
@end
|
||||
|
||||
@interface CDVFile : CDVPlugin {
|
||||
NSString* rootDocsPath;
|
||||
NSString* appDocsPath;
|
||||
NSString* appLibraryPath;
|
||||
NSString* appTempPath;
|
||||
|
||||
NSMutableArray* fileSystems_;
|
||||
BOOL userHasAllowed;
|
||||
}
|
||||
|
||||
- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath;
|
||||
- (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir;
|
||||
- (NSDictionary *)makeEntryForURL:(NSURL *)URL;
|
||||
- (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath;
|
||||
|
||||
- (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL;
|
||||
|
||||
/* Native Registration API */
|
||||
- (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs;
|
||||
- (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName;
|
||||
|
||||
/* Exec API */
|
||||
- (void)requestFileSystem:(CDVInvokedUrlCommand*)command;
|
||||
- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getDirectory:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getFile:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getParent:(CDVInvokedUrlCommand*)command;
|
||||
- (void)removeRecursively:(CDVInvokedUrlCommand*)command;
|
||||
- (void)remove:(CDVInvokedUrlCommand*)command;
|
||||
- (void)copyTo:(CDVInvokedUrlCommand*)command;
|
||||
- (void)moveTo:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getFileMetadata:(CDVInvokedUrlCommand*)command;
|
||||
- (void)readEntries:(CDVInvokedUrlCommand*)command;
|
||||
- (void)readAsText:(CDVInvokedUrlCommand*)command;
|
||||
- (void)readAsDataURL:(CDVInvokedUrlCommand*)command;
|
||||
- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command;
|
||||
- (void)write:(CDVInvokedUrlCommand*)command;
|
||||
- (void)testFileExists:(CDVInvokedUrlCommand*)command;
|
||||
- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command;
|
||||
- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command;
|
||||
- (void)truncate:(CDVInvokedUrlCommand*)command;
|
||||
- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy;
|
||||
|
||||
/* Compatibilty with older File API */
|
||||
- (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
|
||||
- (NSDictionary *)getDirectoryEntry:(NSString *)target isDirectory:(BOOL)bDirRequest;
|
||||
|
||||
/* Conversion between filesystem paths and URLs */
|
||||
- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)URL;
|
||||
|
||||
/* Internal methods for testing */
|
||||
- (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command;
|
||||
|
||||
@property (nonatomic, strong) NSString* rootDocsPath;
|
||||
@property (nonatomic, strong) NSString* appDocsPath;
|
||||
@property (nonatomic, strong) NSString* appLibraryPath;
|
||||
@property (nonatomic, strong) NSString* appTempPath;
|
||||
@property (nonatomic, strong) NSString* persistentPath;
|
||||
@property (nonatomic, strong) NSString* temporaryPath;
|
||||
@property (nonatomic, strong) NSMutableArray* fileSystems;
|
||||
|
||||
@property BOOL userHasAllowed;
|
||||
|
||||
@end
|
||||
|
||||
#define kW3FileTemporary @"temporary"
|
||||
#define kW3FilePersistent @"persistent"
|
1117
platforms/ios/Sensortoy/Plugins/cordova-plugin-file/CDVFile.m
Normal file
1117
platforms/ios/Sensortoy/Plugins/cordova-plugin-file/CDVFile.m
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
#import "CDVFile.h"
|
||||
|
||||
@interface CDVLocalFilesystem : NSObject<CDVFileSystem> {
|
||||
NSString *_name;
|
||||
NSString *_fsRoot;
|
||||
}
|
||||
|
||||
- (id) initWithName:(NSString *)name root:(NSString *)fsRoot;
|
||||
+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
|
||||
|
||||
@property (nonatomic,strong) NSString *fsRoot;
|
||||
|
||||
@end
|
@ -0,0 +1,734 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
#import "CDVFile.h"
|
||||
#import "CDVLocalFilesystem.h"
|
||||
#import <Cordova/CDV.h>
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
#import <sys/xattr.h>
|
||||
|
||||
@implementation CDVLocalFilesystem
|
||||
@synthesize name=_name, fsRoot=_fsRoot, urlTransformer;
|
||||
|
||||
- (id) initWithName:(NSString *)name root:(NSString *)fsRoot
|
||||
{
|
||||
if (self) {
|
||||
self.name = name;
|
||||
self.fsRoot = fsRoot;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* IN
|
||||
* NSString localURI
|
||||
* OUT
|
||||
* CDVPluginResult result containing a file or directoryEntry for the localURI, or an error if the
|
||||
* URI represents a non-existent path, or is unrecognized or otherwise malformed.
|
||||
*/
|
||||
- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
|
||||
{
|
||||
CDVPluginResult* result = nil;
|
||||
NSDictionary* entry = [self makeEntryForLocalURL:url];
|
||||
if (entry) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
|
||||
} else {
|
||||
// return NOT_FOUND_ERR
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
|
||||
NSString *path = [self filesystemPathForURL:url];
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
BOOL isDir = NO;
|
||||
// see if exists and is file or dir
|
||||
BOOL bExists = [fileMgr fileExistsAtPath:path isDirectory:&isDir];
|
||||
if (bExists) {
|
||||
return [self makeEntryForPath:url.fullPath isDirectory:isDir];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
|
||||
{
|
||||
NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
|
||||
NSString* lastPart = [[self stripQueryParametersFromPath:fullPath] lastPathComponent];
|
||||
if (isDir && ![fullPath hasSuffix:@"/"]) {
|
||||
fullPath = [fullPath stringByAppendingString:@"/"];
|
||||
}
|
||||
[dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"];
|
||||
[dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"];
|
||||
[dirEntry setObject:fullPath forKey:@"fullPath"];
|
||||
[dirEntry setObject:lastPart forKey:@"name"];
|
||||
[dirEntry setObject:self.name forKey: @"filesystemName"];
|
||||
|
||||
NSURL* nativeURL = [NSURL fileURLWithPath:[self filesystemPathForFullPath:fullPath]];
|
||||
if (self.urlTransformer) {
|
||||
nativeURL = self.urlTransformer(nativeURL);
|
||||
}
|
||||
|
||||
dirEntry[@"nativeURL"] = [nativeURL absoluteString];
|
||||
|
||||
return dirEntry;
|
||||
}
|
||||
|
||||
- (NSString *)stripQueryParametersFromPath:(NSString *)fullPath
|
||||
{
|
||||
NSRange questionMark = [fullPath rangeOfString:@"?"];
|
||||
if (questionMark.location != NSNotFound) {
|
||||
return [fullPath substringWithRange:NSMakeRange(0,questionMark.location)];
|
||||
}
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
- (NSString *)filesystemPathForFullPath:(NSString *)fullPath
|
||||
{
|
||||
NSString *path = nil;
|
||||
NSString *strippedFullPath = [self stripQueryParametersFromPath:fullPath];
|
||||
path = [NSString stringWithFormat:@"%@%@", self.fsRoot, strippedFullPath];
|
||||
if ([path length] > 1 && [path hasSuffix:@"/"]) {
|
||||
path = [path substringToIndex:([path length]-1)];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
/*
|
||||
* IN
|
||||
* NSString localURI
|
||||
* OUT
|
||||
* NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
|
||||
* The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
|
||||
* or if the URL is malformed.
|
||||
* The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
|
||||
*/
|
||||
- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
|
||||
{
|
||||
return [self filesystemPathForFullPath:url.fullPath];
|
||||
}
|
||||
|
||||
- (CDVFilesystemURL *)URLforFullPath:(NSString *)fullPath
|
||||
{
|
||||
if (fullPath) {
|
||||
NSString* escapedPath = [fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
if ([fullPath hasPrefix:@"/"]) {
|
||||
return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
|
||||
}
|
||||
return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@/%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path
|
||||
{
|
||||
return [self URLforFullPath:[self fullPathForFileSystemPath:path]];
|
||||
|
||||
}
|
||||
|
||||
- (NSString *)normalizePath:(NSString *)rawPath
|
||||
{
|
||||
// If this is an absolute path, the first path component will be '/'. Skip it if that's the case
|
||||
BOOL isAbsolutePath = [rawPath hasPrefix:@"/"];
|
||||
if (isAbsolutePath) {
|
||||
rawPath = [rawPath substringFromIndex:1];
|
||||
}
|
||||
NSMutableArray *components = [NSMutableArray arrayWithArray:[rawPath pathComponents]];
|
||||
for (int index = 0; index < [components count]; ++index) {
|
||||
if ([[components objectAtIndex:index] isEqualToString:@".."]) {
|
||||
[components removeObjectAtIndex:index];
|
||||
if (index > 0) {
|
||||
[components removeObjectAtIndex:index-1];
|
||||
--index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isAbsolutePath) {
|
||||
return [NSString stringWithFormat:@"/%@", [components componentsJoinedByString:@"/"]];
|
||||
} else {
|
||||
return [components componentsJoinedByString:@"/"];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)valueForKeyIsNumber:(NSDictionary*)dict key:(NSString*)key
|
||||
{
|
||||
BOOL bNumber = NO;
|
||||
NSObject* value = dict[key];
|
||||
if (value) {
|
||||
bNumber = [value isKindOfClass:[NSNumber class]];
|
||||
}
|
||||
return bNumber;
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
|
||||
{
|
||||
CDVPluginResult* result = nil;
|
||||
BOOL bDirRequest = NO;
|
||||
BOOL create = NO;
|
||||
BOOL exclusive = NO;
|
||||
int errorCode = 0; // !!! risky - no error code currently defined for 0
|
||||
|
||||
if ([self valueForKeyIsNumber:options key:@"create"]) {
|
||||
create = [(NSNumber*)[options valueForKey:@"create"] boolValue];
|
||||
}
|
||||
if ([self valueForKeyIsNumber:options key:@"exclusive"]) {
|
||||
exclusive = [(NSNumber*)[options valueForKey:@"exclusive"] boolValue];
|
||||
}
|
||||
if ([self valueForKeyIsNumber:options key:@"getDir"]) {
|
||||
// this will not exist for calls directly to getFile but will have been set by getDirectory before calling this method
|
||||
bDirRequest = [(NSNumber*)[options valueForKey:@"getDir"] boolValue];
|
||||
}
|
||||
// see if the requested path has invalid characters - should we be checking for more than just ":"?
|
||||
if ([requestedPath rangeOfString:@":"].location != NSNotFound) {
|
||||
errorCode = ENCODING_ERR;
|
||||
} else {
|
||||
// Build new fullPath for the requested resource.
|
||||
// We concatenate the two paths together, and then scan the resulting string to remove
|
||||
// parent ("..") references. Any parent references at the beginning of the string are
|
||||
// silently removed.
|
||||
NSString *combinedPath = [baseURI.fullPath stringByAppendingPathComponent:requestedPath];
|
||||
combinedPath = [self normalizePath:combinedPath];
|
||||
CDVFilesystemURL* requestedURL = [self URLforFullPath:combinedPath];
|
||||
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
BOOL bIsDir;
|
||||
BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:requestedURL] isDirectory:&bIsDir];
|
||||
if (bExists && (create == NO) && (bIsDir == !bDirRequest)) {
|
||||
// path exists and is not of requested type - return TYPE_MISMATCH_ERR
|
||||
errorCode = TYPE_MISMATCH_ERR;
|
||||
} else if (!bExists && (create == NO)) {
|
||||
// path does not exist and create is false - return NOT_FOUND_ERR
|
||||
errorCode = NOT_FOUND_ERR;
|
||||
} else if (bExists && (create == YES) && (exclusive == YES)) {
|
||||
// file/dir already exists and exclusive and create are both true - return PATH_EXISTS_ERR
|
||||
errorCode = PATH_EXISTS_ERR;
|
||||
} else {
|
||||
// if bExists and create == YES - just return data
|
||||
// if bExists and create == NO - just return data
|
||||
// if !bExists and create == YES - create and return data
|
||||
BOOL bSuccess = YES;
|
||||
NSError __autoreleasing* pError = nil;
|
||||
if (!bExists && (create == YES)) {
|
||||
if (bDirRequest) {
|
||||
// create the dir
|
||||
bSuccess = [fileMgr createDirectoryAtPath:[self filesystemPathForURL:requestedURL] withIntermediateDirectories:NO attributes:nil error:&pError];
|
||||
} else {
|
||||
// create the empty file
|
||||
bSuccess = [fileMgr createFileAtPath:[self filesystemPathForURL:requestedURL] contents:nil attributes:nil];
|
||||
}
|
||||
}
|
||||
if (!bSuccess) {
|
||||
errorCode = ABORT_ERR;
|
||||
if (pError) {
|
||||
NSLog(@"error creating directory: %@", [pError localizedDescription]);
|
||||
}
|
||||
} else {
|
||||
// NSLog(@"newly created file/dir (%@) exists: %d", reqFullPath, [fileMgr fileExistsAtPath:reqFullPath]);
|
||||
// file existed or was created
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:requestedURL.fullPath isDirectory:bDirRequest]];
|
||||
}
|
||||
} // are all possible conditions met?
|
||||
}
|
||||
|
||||
if (errorCode > 0) {
|
||||
// create error callback
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
CDVPluginResult* result = nil;
|
||||
CDVFilesystemURL *newURI = nil;
|
||||
if ([localURI.fullPath isEqualToString:@""]) {
|
||||
// return self
|
||||
newURI = localURI;
|
||||
} else {
|
||||
newURI = [CDVFilesystemURL fileSystemURLWithURL:[localURI.url URLByDeletingLastPathComponent]]; /* TODO: UGLY - FIX */
|
||||
}
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
BOOL bIsDir;
|
||||
BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:newURI] isDirectory:&bIsDir];
|
||||
if (bExists) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:newURI.fullPath isDirectory:bIsDir]];
|
||||
} else {
|
||||
// invalid path or file does not exist
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
|
||||
{
|
||||
BOOL ok = NO;
|
||||
|
||||
NSString* filePath = [self filesystemPathForURL:localURI];
|
||||
// we only care about this iCloud key for now.
|
||||
// set to 1/true to skip backup, set to 0/false to back it up (effectively removing the attribute)
|
||||
NSString* iCloudBackupExtendedAttributeKey = @"com.apple.MobileBackup";
|
||||
id iCloudBackupExtendedAttributeValue = [options objectForKey:iCloudBackupExtendedAttributeKey];
|
||||
|
||||
if ((iCloudBackupExtendedAttributeValue != nil) && [iCloudBackupExtendedAttributeValue isKindOfClass:[NSNumber class]]) {
|
||||
if (IsAtLeastiOSVersion(@"5.1")) {
|
||||
NSURL* url = [NSURL fileURLWithPath:filePath];
|
||||
NSError* __autoreleasing error = nil;
|
||||
|
||||
ok = [url setResourceValue:[NSNumber numberWithBool:[iCloudBackupExtendedAttributeValue boolValue]] forKey:NSURLIsExcludedFromBackupKey error:&error];
|
||||
} else { // below 5.1 (deprecated - only really supported in 5.01)
|
||||
u_int8_t value = [iCloudBackupExtendedAttributeValue intValue];
|
||||
if (value == 0) { // remove the attribute (allow backup, the default)
|
||||
ok = (removexattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], 0) == 0);
|
||||
} else { // set the attribute (skip backup)
|
||||
ok = (setxattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], &value, sizeof(value), 0, 0) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
||||
} else {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the file or directory (recursively)
|
||||
* IN:
|
||||
* NSString* fullPath - the full path to the file or directory to be removed
|
||||
* NSString* callbackId
|
||||
* called from remove and removeRecursively - check all pubic api specific error conditions (dir not empty, etc) before calling
|
||||
*/
|
||||
|
||||
- (CDVPluginResult*)doRemove:(NSString*)fullPath
|
||||
{
|
||||
CDVPluginResult* result = nil;
|
||||
BOOL bSuccess = NO;
|
||||
NSError* __autoreleasing pError = nil;
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
|
||||
@try {
|
||||
bSuccess = [fileMgr removeItemAtPath:fullPath error:&pError];
|
||||
if (bSuccess) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
||||
} else {
|
||||
// see if we can give a useful error
|
||||
CDVFileError errorCode = ABORT_ERR;
|
||||
NSLog(@"error removing filesystem entry at %@: %@", fullPath, [pError localizedDescription]);
|
||||
if ([pError code] == NSFileNoSuchFileError) {
|
||||
errorCode = NOT_FOUND_ERR;
|
||||
} else if ([pError code] == NSFileWriteNoPermissionError) {
|
||||
errorCode = NO_MODIFICATION_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
|
||||
}
|
||||
} @catch(NSException* e) { // NSInvalidArgumentException if path is . or ..
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:SYNTAX_ERR];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
NSString *fileSystemPath = [self filesystemPathForURL:localURI];
|
||||
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
BOOL bIsDir = NO;
|
||||
BOOL bExists = [fileMgr fileExistsAtPath:fileSystemPath isDirectory:&bIsDir];
|
||||
if (!bExists) {
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
|
||||
}
|
||||
if (bIsDir && ([[fileMgr contentsOfDirectoryAtPath:fileSystemPath error:nil] count] != 0)) {
|
||||
// dir is not empty
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
|
||||
}
|
||||
return [self doRemove:fileSystemPath];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
NSString *fileSystemPath = [self filesystemPathForURL:localURI];
|
||||
return [self doRemove:fileSystemPath];
|
||||
}
|
||||
|
||||
/*
|
||||
* IN
|
||||
* NSString localURI
|
||||
* OUT
|
||||
* NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
|
||||
* The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
|
||||
* or if the URL is malformed.
|
||||
* The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
|
||||
*/
|
||||
- (NSString *)fullPathForFileSystemPath:(NSString *)fsPath
|
||||
{
|
||||
if ([fsPath hasPrefix:self.fsRoot]) {
|
||||
return [fsPath substringFromIndex:[self.fsRoot length]];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
|
||||
{
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
NSError* __autoreleasing error = nil;
|
||||
NSString *fileSystemPath = [self filesystemPathForURL:localURI];
|
||||
|
||||
NSArray* contents = [fileMgr contentsOfDirectoryAtPath:fileSystemPath error:&error];
|
||||
|
||||
if (contents) {
|
||||
NSMutableArray* entries = [NSMutableArray arrayWithCapacity:1];
|
||||
if ([contents count] > 0) {
|
||||
// create an Entry (as JSON) for each file/dir
|
||||
for (NSString* name in contents) {
|
||||
// see if is dir or file
|
||||
NSString* entryPath = [fileSystemPath stringByAppendingPathComponent:name];
|
||||
BOOL bIsDir = NO;
|
||||
[fileMgr fileExistsAtPath:entryPath isDirectory:&bIsDir];
|
||||
NSDictionary* entryDict = [self makeEntryForPath:[self fullPathForFileSystemPath:entryPath] isDirectory:bIsDir];
|
||||
[entries addObject:entryDict];
|
||||
}
|
||||
}
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:entries];
|
||||
} else {
|
||||
// assume not found but could check error for more specific error conditions
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned long long)truncateFile:(NSString*)filePath atPosition:(unsigned long long)pos
|
||||
{
|
||||
unsigned long long newPos = 0UL;
|
||||
|
||||
NSFileHandle* file = [NSFileHandle fileHandleForWritingAtPath:filePath];
|
||||
|
||||
if (file) {
|
||||
[file truncateFileAtOffset:(unsigned long long)pos];
|
||||
newPos = [file offsetInFile];
|
||||
[file synchronizeFile];
|
||||
[file closeFile];
|
||||
}
|
||||
return newPos;
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
|
||||
{
|
||||
unsigned long long newPos = [self truncateFile:[self filesystemPathForURL:localURI] atPosition:pos];
|
||||
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)newPos];
|
||||
}
|
||||
|
||||
- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
|
||||
{
|
||||
NSString *filePath = [self filesystemPathForURL:localURL];
|
||||
|
||||
CDVPluginResult* result = nil;
|
||||
CDVFileError errCode = INVALID_MODIFICATION_ERR;
|
||||
int bytesWritten = 0;
|
||||
|
||||
if (filePath) {
|
||||
NSOutputStream* fileStream = [NSOutputStream outputStreamToFileAtPath:filePath append:shouldAppend];
|
||||
if (fileStream) {
|
||||
NSUInteger len = [encData length];
|
||||
if (len == 0) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:(double)len];
|
||||
} else {
|
||||
[fileStream open];
|
||||
|
||||
bytesWritten = (int)[fileStream write:[encData bytes] maxLength:len];
|
||||
|
||||
[fileStream close];
|
||||
if (bytesWritten > 0) {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:bytesWritten];
|
||||
// } else {
|
||||
// can probably get more detailed error info via [fileStream streamError]
|
||||
// errCode already set to INVALID_MODIFICATION_ERR;
|
||||
// bytesWritten = 0; // may be set to -1 on error
|
||||
}
|
||||
}
|
||||
} // else fileStream not created return INVALID_MODIFICATION_ERR
|
||||
} else {
|
||||
// invalid filePath
|
||||
errCode = NOT_FOUND_ERR;
|
||||
}
|
||||
if (!result) {
|
||||
// was an error
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to check to see if the user attempted to copy an entry into its parent without changing its name,
|
||||
* or attempted to copy a directory into a directory that it contains directly or indirectly.
|
||||
*
|
||||
* IN:
|
||||
* NSString* srcDir
|
||||
* NSString* destinationDir
|
||||
* OUT:
|
||||
* YES copy/ move is allows
|
||||
* NO move is onto itself
|
||||
*/
|
||||
- (BOOL)canCopyMoveSrc:(NSString*)src ToDestination:(NSString*)dest
|
||||
{
|
||||
// This weird test is to determine if we are copying or moving a directory into itself.
|
||||
// Copy /Documents/myDir to /Documents/myDir-backup is okay but
|
||||
// Copy /Documents/myDir to /Documents/myDir/backup not okay
|
||||
BOOL copyOK = YES;
|
||||
NSRange range = [dest rangeOfString:src];
|
||||
|
||||
if (range.location != NSNotFound) {
|
||||
NSRange testRange = {range.length - 1, ([dest length] - range.length)};
|
||||
NSRange resultRange = [dest rangeOfString:@"/" options:0 range:testRange];
|
||||
if (resultRange.location != NSNotFound) {
|
||||
copyOK = NO;
|
||||
}
|
||||
}
|
||||
return copyOK;
|
||||
}
|
||||
|
||||
- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
|
||||
{
|
||||
NSFileManager *fileMgr = [[NSFileManager alloc] init];
|
||||
NSString *destRootPath = [self filesystemPathForURL:destURL];
|
||||
BOOL bDestIsDir = NO;
|
||||
BOOL bDestExists = [fileMgr fileExistsAtPath:destRootPath isDirectory:&bDestIsDir];
|
||||
|
||||
NSString *newFileSystemPath = [destRootPath stringByAppendingPathComponent:newName];
|
||||
NSString *newFullPath = [self fullPathForFileSystemPath:newFileSystemPath];
|
||||
|
||||
BOOL bNewIsDir = NO;
|
||||
BOOL bNewExists = [fileMgr fileExistsAtPath:newFileSystemPath isDirectory:&bNewIsDir];
|
||||
|
||||
CDVPluginResult *result = nil;
|
||||
int errCode = 0;
|
||||
|
||||
if (!bDestExists) {
|
||||
// the destination root does not exist
|
||||
errCode = NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
else if ([srcFs isKindOfClass:[CDVLocalFilesystem class]]) {
|
||||
/* Same FS, we can shortcut with NSFileManager operations */
|
||||
NSString *srcFullPath = [srcFs filesystemPathForURL:srcURL];
|
||||
|
||||
BOOL bSrcIsDir = NO;
|
||||
BOOL bSrcExists = [fileMgr fileExistsAtPath:srcFullPath isDirectory:&bSrcIsDir];
|
||||
|
||||
if (!bSrcExists) {
|
||||
// the source does not exist
|
||||
errCode = NOT_FOUND_ERR;
|
||||
} else if ([newFileSystemPath isEqualToString:srcFullPath]) {
|
||||
// source and destination can not be the same
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
} else if (bSrcIsDir && (bNewExists && !bNewIsDir)) {
|
||||
// can't copy/move dir to file
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
} else { // no errors yet
|
||||
NSError* __autoreleasing error = nil;
|
||||
BOOL bSuccess = NO;
|
||||
if (bCopy) {
|
||||
if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
|
||||
// can't copy dir into self
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
} else if (bNewExists) {
|
||||
// the full destination should NOT already exist if a copy
|
||||
errCode = PATH_EXISTS_ERR;
|
||||
} else {
|
||||
bSuccess = [fileMgr copyItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
|
||||
}
|
||||
} else { // move
|
||||
// iOS requires that destination must not exist before calling moveTo
|
||||
// is W3C INVALID_MODIFICATION_ERR error if destination dir exists and has contents
|
||||
//
|
||||
if (!bSrcIsDir && (bNewExists && bNewIsDir)) {
|
||||
// can't move a file to directory
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
} else if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
|
||||
// can't move a dir into itself
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
} else if (bNewExists) {
|
||||
if (bNewIsDir && ([[fileMgr contentsOfDirectoryAtPath:newFileSystemPath error:NULL] count] != 0)) {
|
||||
// can't move dir to a dir that is not empty
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
newFileSystemPath = nil; // so we won't try to move
|
||||
} else {
|
||||
// remove destination so can perform the moveItemAtPath
|
||||
bSuccess = [fileMgr removeItemAtPath:newFileSystemPath error:NULL];
|
||||
if (!bSuccess) {
|
||||
errCode = INVALID_MODIFICATION_ERR; // is this the correct error?
|
||||
newFileSystemPath = nil;
|
||||
}
|
||||
}
|
||||
} else if (bNewIsDir && [newFileSystemPath hasPrefix:srcFullPath]) {
|
||||
// can't move a directory inside itself or to any child at any depth;
|
||||
errCode = INVALID_MODIFICATION_ERR;
|
||||
newFileSystemPath = nil;
|
||||
}
|
||||
|
||||
if (newFileSystemPath != nil) {
|
||||
bSuccess = [fileMgr moveItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
|
||||
}
|
||||
}
|
||||
if (bSuccess) {
|
||||
// should verify it is there and of the correct type???
|
||||
NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:bSrcIsDir];
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
|
||||
} else {
|
||||
if (error) {
|
||||
if (([error code] == NSFileReadUnknownError) || ([error code] == NSFileReadTooLargeError)) {
|
||||
errCode = NOT_READABLE_ERR;
|
||||
} else if ([error code] == NSFileWriteOutOfSpaceError) {
|
||||
errCode = QUOTA_EXCEEDED_ERR;
|
||||
} else if ([error code] == NSFileWriteNoPermissionError) {
|
||||
errCode = NO_MODIFICATION_ALLOWED_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Need to copy the hard way
|
||||
[srcFs readFileAtURL:srcURL start:0 end:-1 callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
|
||||
CDVPluginResult* result = nil;
|
||||
if (data != nil) {
|
||||
BOOL bSuccess = [data writeToFile:newFileSystemPath atomically:YES];
|
||||
if (bSuccess) {
|
||||
// should verify it is there and of the correct type???
|
||||
NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:NO];
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
|
||||
} else {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ABORT_ERR];
|
||||
}
|
||||
} else {
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
|
||||
}
|
||||
callback(result);
|
||||
}];
|
||||
return; // Async IO; return without callback.
|
||||
}
|
||||
if (result == nil) {
|
||||
if (!errCode) {
|
||||
errCode = INVALID_MODIFICATION_ERR; // Catch-all default
|
||||
}
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errCode];
|
||||
}
|
||||
callback(result);
|
||||
}
|
||||
|
||||
/* helper function to get the mimeType from the file extension
|
||||
* IN:
|
||||
* NSString* fullPath - filename (may include path)
|
||||
* OUT:
|
||||
* NSString* the mime type as type/subtype. nil if not able to determine
|
||||
*/
|
||||
+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
|
||||
{
|
||||
NSString* mimeType = nil;
|
||||
|
||||
if (fullPath) {
|
||||
CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
|
||||
if (typeId) {
|
||||
mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
|
||||
if (!mimeType) {
|
||||
// special case for m4a
|
||||
if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
|
||||
mimeType = @"audio/mp4";
|
||||
} else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
|
||||
mimeType = @"audio/wav";
|
||||
} else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
|
||||
mimeType = @"text/css";
|
||||
}
|
||||
}
|
||||
CFRelease(typeId);
|
||||
}
|
||||
}
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
|
||||
{
|
||||
NSString *path = [self filesystemPathForURL:localURL];
|
||||
|
||||
NSString* mimeType = [CDVLocalFilesystem getMimeTypeFromPath:path];
|
||||
if (mimeType == nil) {
|
||||
mimeType = @"*/*";
|
||||
}
|
||||
NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:path];
|
||||
if (start > 0) {
|
||||
[file seekToFileOffset:start];
|
||||
}
|
||||
|
||||
NSData* readData;
|
||||
if (end < 0) {
|
||||
readData = [file readDataToEndOfFile];
|
||||
} else {
|
||||
readData = [file readDataOfLength:(end - start)];
|
||||
}
|
||||
[file closeFile];
|
||||
|
||||
callback(readData, mimeType, readData != nil ? NO_ERROR : NOT_FOUND_ERR);
|
||||
}
|
||||
|
||||
- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
|
||||
{
|
||||
NSString *path = [self filesystemPathForURL:localURL];
|
||||
CDVPluginResult *result;
|
||||
NSFileManager* fileMgr = [[NSFileManager alloc] init];
|
||||
|
||||
NSError* __autoreleasing error = nil;
|
||||
NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:path error:&error];
|
||||
|
||||
if (fileAttrs) {
|
||||
|
||||
// create dictionary of file info
|
||||
NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
|
||||
|
||||
[fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
|
||||
[fileInfo setObject:@"" forKey:@"type"]; // can't easily get the mimetype unless create URL, send request and read response so skipping
|
||||
[fileInfo setObject:[path lastPathComponent] forKey:@"name"];
|
||||
|
||||
// Ensure that directories (and other non-regular files) report size of 0
|
||||
unsigned long long size = ([fileAttrs fileType] == NSFileTypeRegular ? [fileAttrs fileSize] : 0);
|
||||
[fileInfo setObject:[NSNumber numberWithUnsignedLongLong:size] forKey:@"size"];
|
||||
|
||||
NSDate* modDate = [fileAttrs fileModificationDate];
|
||||
if (modDate) {
|
||||
[fileInfo setObject:[NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000] forKey:@"lastModifiedDate"];
|
||||
}
|
||||
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo];
|
||||
|
||||
} else {
|
||||
// didn't get fileAttribs
|
||||
CDVFileError errorCode = ABORT_ERR;
|
||||
NSLog(@"error getting metadata: %@", [error localizedDescription]);
|
||||
if ([error code] == NSFileNoSuchFileError || [error code] == NSFileReadNoSuchFileError) {
|
||||
errorCode = NOT_FOUND_ERR;
|
||||
}
|
||||
// log [NSNumber numberWithDouble: theMessage] objCtype to see what it returns
|
||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode];
|
||||
}
|
||||
|
||||
callback(result);
|
||||
}
|
||||
|
||||
@end
|
120
platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
120
platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileError = require('./FileError'),
|
||||
DirectoryReader = require('./DirectoryReader');
|
||||
|
||||
/**
|
||||
* An interface representing a directory on the file system.
|
||||
*
|
||||
* {boolean} isFile always false (readonly)
|
||||
* {boolean} isDirectory always true (readonly)
|
||||
* {DOMString} name of the directory, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the directory (readonly)
|
||||
* {FileSystem} filesystem on which the directory resides (readonly)
|
||||
*/
|
||||
var DirectoryEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
|
||||
// add trailing slash if it is missing
|
||||
if ((fullPath) && !/\/$/.test(fullPath)) {
|
||||
fullPath += "/";
|
||||
}
|
||||
// add trailing slash if it is missing
|
||||
if (nativeURL && !/\/$/.test(nativeURL)) {
|
||||
nativeURL += "/";
|
||||
}
|
||||
DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
|
||||
};
|
||||
|
||||
utils.extend(DirectoryEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new DirectoryReader to read entries from this directory
|
||||
*/
|
||||
DirectoryEntry.prototype.createReader = function() {
|
||||
return new DirectoryReader(this.toInternalURL());
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a directory
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
|
||||
* @param {Flags} options to create or exclusively create the directory
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getDirectory", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a directory and all of it's contents
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "removeRecursively", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a file
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
|
||||
* @param {Flags} options to create or exclusively create the file
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var FileEntry = require('./FileEntry');
|
||||
var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFile", [this.toInternalURL(), path, options]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryEntry;
|
||||
|
||||
});
|
76
platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
76
platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError') ;
|
||||
|
||||
/**
|
||||
* An interface that lists the files and directories in a directory.
|
||||
*/
|
||||
function DirectoryReader(localURL) {
|
||||
this.localURL = localURL || null;
|
||||
this.hasReadEntries = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of entries from a directory.
|
||||
*
|
||||
* @param {Function} successCallback is called with a list of entries
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
|
||||
// If we've already read and passed on this directory's entries, return an empty list.
|
||||
if (this.hasReadEntries) {
|
||||
successCallback([]);
|
||||
return;
|
||||
}
|
||||
var reader = this;
|
||||
var win = typeof successCallback !== 'function' ? null : function(result) {
|
||||
var retVal = [];
|
||||
for (var i=0; i<result.length; i++) {
|
||||
var entry = null;
|
||||
if (result[i].isDirectory) {
|
||||
entry = new (require('./DirectoryEntry'))();
|
||||
}
|
||||
else if (result[i].isFile) {
|
||||
entry = new (require('./FileEntry'))();
|
||||
}
|
||||
entry.isDirectory = result[i].isDirectory;
|
||||
entry.isFile = result[i].isFile;
|
||||
entry.name = result[i].name;
|
||||
entry.fullPath = result[i].fullPath;
|
||||
entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
|
||||
entry.nativeURL = result[i].nativeURL;
|
||||
retVal.push(entry);
|
||||
}
|
||||
reader.hasReadEntries = true;
|
||||
successCallback(retVal);
|
||||
};
|
||||
var fail = typeof errorCallback !== 'function' ? null : function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "readEntries", [this.localURL]);
|
||||
};
|
||||
|
||||
module.exports = DirectoryReader;
|
||||
|
||||
});
|
265
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
265
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Entry.js
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var argscheck = require('cordova/argscheck'),
|
||||
exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
Metadata = require('./Metadata');
|
||||
|
||||
/**
|
||||
* Represents a file or directory on the local file system.
|
||||
*
|
||||
* @param isFile
|
||||
* {boolean} true if Entry is a file (readonly)
|
||||
* @param isDirectory
|
||||
* {boolean} true if Entry is a directory (readonly)
|
||||
* @param name
|
||||
* {DOMString} name of the file or directory, excluding the path
|
||||
* leading to it (readonly)
|
||||
* @param fullPath
|
||||
* {DOMString} the absolute full path to the file or directory
|
||||
* (readonly)
|
||||
* @param fileSystem
|
||||
* {FileSystem} the filesystem on which this entry resides
|
||||
* (readonly)
|
||||
* @param nativeURL
|
||||
* {DOMString} an alternate URL which can be used by native
|
||||
* webview controls, for example media players.
|
||||
* (optional, readonly)
|
||||
*/
|
||||
function Entry(isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
|
||||
this.isFile = !!isFile;
|
||||
this.isDirectory = !!isDirectory;
|
||||
this.name = name || '';
|
||||
this.fullPath = fullPath || '';
|
||||
this.filesystem = fileSystem || null;
|
||||
this.nativeURL = nativeURL || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
*/
|
||||
Entry.prototype.getMetadata = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
|
||||
var success = successCallback && function(entryMetadata) {
|
||||
var metadata = new Metadata({
|
||||
size: entryMetadata.size,
|
||||
modificationTime: entryMetadata.lastModifiedDate
|
||||
});
|
||||
successCallback(metadata);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(success, fail, "File", "getFileMetadata", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the metadata of the entry.
|
||||
*
|
||||
* @param successCallback
|
||||
* {Function} is called with a Metadata object
|
||||
* @param errorCallback
|
||||
* {Function} is called with a FileError
|
||||
* @param metadataObject
|
||||
* {Object} keys and values to set
|
||||
*/
|
||||
Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
|
||||
argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
|
||||
exec(successCallback, errorCallback, "File", "setMetadata", [this.toInternalURL(), metadataObject]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a file or directory to a new location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to move this entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new DirectoryEntry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "moveTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a directory to a different location.
|
||||
*
|
||||
* @param parent
|
||||
* {DirectoryEntry} the directory to which to copy the entry
|
||||
* @param newName
|
||||
* {DOMString} new name of the entry, defaults to the current name
|
||||
* @param successCallback
|
||||
* {Function} called with the new Entry object
|
||||
* @param errorCallback
|
||||
* {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
|
||||
argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
var srcURL = this.toInternalURL(),
|
||||
// entry name
|
||||
name = newName || this.name,
|
||||
// success callback
|
||||
success = function(entry) {
|
||||
if (entry) {
|
||||
if (successCallback) {
|
||||
// create appropriate Entry object
|
||||
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
|
||||
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
|
||||
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
|
||||
successCallback(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no Entry object returned
|
||||
if (fail) {
|
||||
fail(FileError.NOT_FOUND_ERR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// copy
|
||||
exec(success, fail, "File", "copyTo", [srcURL, parent.toInternalURL(), name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be passed across the bridge to identify this entry.
|
||||
*/
|
||||
Entry.prototype.toInternalURL = function() {
|
||||
if (this.filesystem && this.filesystem.__format__) {
|
||||
return this.filesystem.__format__(this.fullPath, this.nativeURL);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a URL that can be used to identify this entry.
|
||||
* Use a URL that can be used to as the src attribute of a <video> or
|
||||
* <audio> tag. If that is not possible, construct a cdvfile:// URL.
|
||||
*/
|
||||
Entry.prototype.toURL = function() {
|
||||
if (this.nativeURL) {
|
||||
return this.nativeURL;
|
||||
}
|
||||
// fullPath attribute may contain the full URL in the case that
|
||||
// toInternalURL fails.
|
||||
return this.toInternalURL() || "file://localhost" + this.fullPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
|
||||
* cdvfile:// URL, and this method was necessary to obtain URLs usable by the
|
||||
* webview.
|
||||
* See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
|
||||
* and CB-6300.
|
||||
*/
|
||||
Entry.prototype.toNativeURL = function() {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a URI that can be used to identify this entry.
|
||||
*
|
||||
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
|
||||
* @return uri
|
||||
*/
|
||||
Entry.prototype.toURI = function(mimeType) {
|
||||
console.log("DEPRECATED: Update your code to use 'toURL'");
|
||||
return this.toURL();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a file or directory. It is an error to attempt to delete a
|
||||
* directory that is not empty. It is an error to attempt to delete a
|
||||
* root directory of a file system.
|
||||
*
|
||||
* @param successCallback {Function} called with no parameters
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.remove = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.remove', arguments);
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(successCallback, fail, "File", "remove", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Look up the parent DirectoryEntry of this entry.
|
||||
*
|
||||
* @param successCallback {Function} called with the parent DirectoryEntry object
|
||||
* @param errorCallback {Function} called with a FileError
|
||||
*/
|
||||
Entry.prototype.getParent = function(successCallback, errorCallback) {
|
||||
argscheck.checkArgs('FF', 'Entry.getParent', arguments);
|
||||
var fs = this.filesystem;
|
||||
var win = successCallback && function(result) {
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
|
||||
successCallback(entry);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getParent", [this.toInternalURL()]);
|
||||
};
|
||||
|
||||
module.exports = Entry;
|
||||
|
||||
});
|
82
platforms/ios/platform_www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
82
platforms/ios/platform_www/plugins/cordova-plugin-file/www/File.js
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
cordova.define("cordova-plugin-file.File", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* name {DOMString} name of the file, without path information
|
||||
* fullPath {DOMString} the full path of the file, including the name
|
||||
* type {DOMString} mime type
|
||||
* lastModifiedDate {Date} last modified date
|
||||
* size {Number} size of the file in bytes
|
||||
*/
|
||||
|
||||
var File = function(name, localURL, type, lastModifiedDate, size){
|
||||
this.name = name || '';
|
||||
this.localURL = localURL || null;
|
||||
this.type = type || null;
|
||||
this.lastModified = lastModifiedDate || null;
|
||||
// For backwards compatibility, store the timestamp in lastModifiedDate as well
|
||||
this.lastModifiedDate = lastModifiedDate || null;
|
||||
this.size = size || 0;
|
||||
|
||||
// These store the absolute start and end for slicing the file.
|
||||
this.start = 0;
|
||||
this.end = this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a "slice" of the file. Since Cordova Files don't contain the actual
|
||||
* content, this really returns a File with adjusted start and end.
|
||||
* Slices of slices are supported.
|
||||
* start {Number} The index at which to start the slice (inclusive).
|
||||
* end {Number} The index at which to end the slice (exclusive).
|
||||
*/
|
||||
File.prototype.slice = function(start, end) {
|
||||
var size = this.end - this.start;
|
||||
var newStart = 0;
|
||||
var newEnd = size;
|
||||
if (arguments.length) {
|
||||
if (start < 0) {
|
||||
newStart = Math.max(size + start, 0);
|
||||
} else {
|
||||
newStart = Math.min(size, start);
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.length >= 2) {
|
||||
if (end < 0) {
|
||||
newEnd = Math.max(size + end, 0);
|
||||
} else {
|
||||
newEnd = Math.min(end, size);
|
||||
}
|
||||
}
|
||||
|
||||
var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
|
||||
newFile.start = this.start + newStart;
|
||||
newFile.end = this.start + newEnd;
|
||||
return newFile;
|
||||
};
|
||||
|
||||
|
||||
module.exports = File;
|
||||
|
||||
});
|
96
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
96
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var utils = require('cordova/utils'),
|
||||
exec = require('cordova/exec'),
|
||||
Entry = require('./Entry'),
|
||||
FileWriter = require('./FileWriter'),
|
||||
File = require('./File'),
|
||||
FileError = require('./FileError');
|
||||
|
||||
/**
|
||||
* An interface representing a file on the file system.
|
||||
*
|
||||
* {boolean} isFile always true (readonly)
|
||||
* {boolean} isDirectory always false (readonly)
|
||||
* {DOMString} name of the file, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the file (readonly)
|
||||
* {FileSystem} filesystem on which the file resides (readonly)
|
||||
*/
|
||||
var FileEntry = function(name, fullPath, fileSystem, nativeURL) {
|
||||
// remove trailing slash if it is present
|
||||
if (fullPath && /\/$/.test(fullPath)) {
|
||||
fullPath = fullPath.substring(0, fullPath.length - 1);
|
||||
}
|
||||
if (nativeURL && /\/$/.test(nativeURL)) {
|
||||
nativeURL = nativeURL.substring(0, nativeURL.length - 1);
|
||||
}
|
||||
|
||||
FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
|
||||
};
|
||||
|
||||
utils.extend(FileEntry, Entry);
|
||||
|
||||
/**
|
||||
* Creates a new FileWriter associated with the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new FileWriter
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
|
||||
this.file(function(filePointer) {
|
||||
var writer = new FileWriter(filePointer);
|
||||
|
||||
if (writer.localURL === null || writer.localURL === "") {
|
||||
if (errorCallback) {
|
||||
errorCallback(new FileError(FileError.INVALID_STATE_ERR));
|
||||
}
|
||||
} else {
|
||||
if (successCallback) {
|
||||
successCallback(writer);
|
||||
}
|
||||
}
|
||||
}, errorCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a File that represents the current state of the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new File object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.file = function(successCallback, errorCallback) {
|
||||
var localURL = this.toInternalURL();
|
||||
var win = successCallback && function(f) {
|
||||
var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
|
||||
successCallback(file);
|
||||
};
|
||||
var fail = errorCallback && function(code) {
|
||||
errorCallback(new FileError(code));
|
||||
};
|
||||
exec(win, fail, "File", "getFileMetadata", [localURL]);
|
||||
};
|
||||
|
||||
|
||||
module.exports = FileEntry;
|
||||
|
||||
});
|
49
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
49
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileError.js
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileError
|
||||
*/
|
||||
function FileError(error) {
|
||||
this.code = error || null;
|
||||
}
|
||||
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
FileError.NOT_FOUND_ERR = 1;
|
||||
FileError.SECURITY_ERR = 2;
|
||||
FileError.ABORT_ERR = 3;
|
||||
|
||||
// Added by File API specification
|
||||
FileError.NOT_READABLE_ERR = 4;
|
||||
FileError.ENCODING_ERR = 5;
|
||||
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
FileError.INVALID_STATE_ERR = 7;
|
||||
FileError.SYNTAX_ERR = 8;
|
||||
FileError.INVALID_MODIFICATION_ERR = 9;
|
||||
FileError.QUOTA_EXCEEDED_ERR = 10;
|
||||
FileError.TYPE_MISMATCH_ERR = 11;
|
||||
FileError.PATH_EXISTS_ERR = 12;
|
||||
|
||||
module.exports = FileError;
|
||||
|
||||
});
|
292
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
292
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileReader.js
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
modulemapper = require('cordova/modulemapper'),
|
||||
utils = require('cordova/utils'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent'),
|
||||
origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
|
||||
|
||||
/**
|
||||
* This class reads the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To read from the SD card, the file name is "sdcard/my_file.txt"
|
||||
* @constructor
|
||||
*/
|
||||
var FileReader = function() {
|
||||
this._readyState = 0;
|
||||
this._error = null;
|
||||
this._result = null;
|
||||
this._progress = null;
|
||||
this._localURL = '';
|
||||
this._realReader = origFileReader ? new origFileReader() : {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the maximum size to read at a time via the native API. The default value is a compromise between
|
||||
* minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
|
||||
* (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
|
||||
* OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
|
||||
*/
|
||||
FileReader.READ_CHUNK_SIZE = 256*1024;
|
||||
|
||||
// States
|
||||
FileReader.EMPTY = 0;
|
||||
FileReader.LOADING = 1;
|
||||
FileReader.DONE = 2;
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'readyState', function() {
|
||||
return this._localURL ? this._readyState : this._realReader.readyState;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'error', function() {
|
||||
return this._localURL ? this._error: this._realReader.error;
|
||||
});
|
||||
|
||||
utils.defineGetter(FileReader.prototype, 'result', function() {
|
||||
return this._localURL ? this._result: this._realReader.result;
|
||||
});
|
||||
|
||||
function defineEvent(eventName) {
|
||||
utils.defineGetterSetter(FileReader.prototype, eventName, function() {
|
||||
return this._realReader[eventName] || null;
|
||||
}, function(value) {
|
||||
this._realReader[eventName] = value;
|
||||
});
|
||||
}
|
||||
defineEvent('onloadstart'); // When the read starts.
|
||||
defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
|
||||
defineEvent('onload'); // When the read has successfully completed.
|
||||
defineEvent('onerror'); // When the read has failed (see errors).
|
||||
defineEvent('onloadend'); // When the request has completed (either in success or failure).
|
||||
defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
|
||||
|
||||
function initRead(reader, file) {
|
||||
// Already loading something
|
||||
if (reader.readyState == FileReader.LOADING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
reader._result = null;
|
||||
reader._error = null;
|
||||
reader._progress = 0;
|
||||
reader._readyState = FileReader.LOADING;
|
||||
|
||||
if (typeof file.localURL == 'string') {
|
||||
reader._localURL = file.localURL;
|
||||
} else {
|
||||
reader._localURL = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reader.onloadstart) {
|
||||
reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle incremental or final success.
|
||||
* Must be bound to the FileReader's this along with all but the last parameter,
|
||||
* e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
|
||||
* @param readType The name of the read function to call.
|
||||
* @param encoding Text encoding, or null if this is not a text type read.
|
||||
* @param offset Starting offset of the read.
|
||||
* @param totalSize Total number of bytes or chars to read.
|
||||
* @param accumulate A function that takes the callback result and accumulates it in this._result.
|
||||
* @param r Callback result returned by the last read exec() call, or null to begin reading.
|
||||
*/
|
||||
function readSuccessCallback(readType, encoding, offset, totalSize, accumulate, r) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof r !== "undefined") {
|
||||
accumulate(r);
|
||||
this._progress = Math.min(this._progress + FileReader.READ_CHUNK_SIZE, totalSize);
|
||||
|
||||
if (typeof this.onprogress === "function") {
|
||||
this.onprogress(new ProgressEvent("progress", {loaded:this._progress, total:totalSize}));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof r === "undefined" || this._progress < totalSize) {
|
||||
var execArgs = [
|
||||
this._localURL,
|
||||
offset + this._progress,
|
||||
offset + this._progress + Math.min(totalSize - this._progress, FileReader.READ_CHUNK_SIZE)];
|
||||
if (encoding) {
|
||||
execArgs.splice(1, 0, encoding);
|
||||
}
|
||||
exec(
|
||||
readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
|
||||
readFailureCallback.bind(this),
|
||||
"File", readType, execArgs);
|
||||
} else {
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
if (typeof this.onload === "function") {
|
||||
this.onload(new ProgressEvent("load", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used by the following read* functions to handle errors.
|
||||
* Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
|
||||
*/
|
||||
function readFailureCallback(e) {
|
||||
if (this._readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
this._result = null;
|
||||
this._error = new FileError(e);
|
||||
|
||||
if (typeof this.onerror === "function") {
|
||||
this.onerror(new ProgressEvent("error", {target:this}));
|
||||
}
|
||||
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend(new ProgressEvent("loadend", {target:this}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort reading file.
|
||||
*/
|
||||
FileReader.prototype.abort = function() {
|
||||
if (origFileReader && !this._localURL) {
|
||||
return this._realReader.abort();
|
||||
}
|
||||
this._result = null;
|
||||
|
||||
if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._readyState = FileReader.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === 'function') {
|
||||
this.onabort(new ProgressEvent('abort', {target:this}));
|
||||
}
|
||||
// If load end callback
|
||||
if (typeof this.onloadend === 'function') {
|
||||
this.onloadend(new ProgressEvent('loadend', {target:this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Read text file.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
|
||||
*/
|
||||
FileReader.prototype.readAsText = function(file, encoding) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsText(file, encoding);
|
||||
}
|
||||
|
||||
// Default encoding is UTF-8
|
||||
var enc = encoding ? encoding : "UTF-8";
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsText", enc, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read file and return data as a base64 encoded data url.
|
||||
* A data url is of the form:
|
||||
* data:[<mediatype>][;base64],<data>
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsDataURL = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsDataURL", null, file.start, totalSize, function(r) {
|
||||
var commaIndex = r.indexOf(',');
|
||||
if (this._progress === 0) {
|
||||
this._result = r;
|
||||
} else {
|
||||
this._result += r.substring(commaIndex + 1);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsBinaryString = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsBinaryString(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsBinaryString", null, file.start, totalSize, function(r) {
|
||||
if (this._progress === 0) {
|
||||
this._result = "";
|
||||
}
|
||||
this._result += r;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsArrayBuffer = function(file) {
|
||||
if (initRead(this, file)) {
|
||||
return this._realReader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
var totalSize = file.end - file.start;
|
||||
readSuccessCallback.bind(this)("readAsArrayBuffer", null, file.start, totalSize, function(r) {
|
||||
var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
|
||||
resultArray.set(new Uint8Array(r), this._progress);
|
||||
this._result = resultArray.buffer;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
module.exports = FileReader;
|
||||
|
||||
});
|
58
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
58
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var DirectoryEntry = require('./DirectoryEntry');
|
||||
|
||||
/**
|
||||
* An interface representing a file system
|
||||
*
|
||||
* @constructor
|
||||
* {DOMString} name the unique name of the file system (readonly)
|
||||
* {DirectoryEntry} root directory of the file system (readonly)
|
||||
*/
|
||||
var FileSystem = function(name, root) {
|
||||
this.name = name;
|
||||
if (root) {
|
||||
this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
|
||||
} else {
|
||||
this.root = new DirectoryEntry(this.name, '/', this);
|
||||
}
|
||||
};
|
||||
|
||||
FileSystem.prototype.__format__ = function(fullPath, nativeUrl) {
|
||||
return fullPath;
|
||||
};
|
||||
|
||||
FileSystem.prototype.toJSON = function() {
|
||||
return "<FileSystem: " + this.name + ">";
|
||||
};
|
||||
|
||||
// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
|
||||
FileSystem.encodeURIPath = function(path) {
|
||||
// Because # is a valid filename character, it must be encoded to prevent part of the
|
||||
// path from being parsed as a URI fragment.
|
||||
return encodeURI(path).replace(/#/g, '%23');
|
||||
};
|
||||
|
||||
module.exports = FileSystem;
|
||||
|
||||
});
|
44
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
44
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options to customize the HTTP request used to upload files.
|
||||
* @constructor
|
||||
* @param fileKey {String} Name of file request parameter.
|
||||
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
|
||||
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
|
||||
* @param params {Object} Object with key: value params to send to the server.
|
||||
* @param headers {Object} Keys are header names, values are header values. Multiple
|
||||
* headers of the same name are not supported.
|
||||
*/
|
||||
var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
|
||||
this.fileKey = fileKey || null;
|
||||
this.fileName = fileName || null;
|
||||
this.mimeType = mimeType || null;
|
||||
this.params = params || null;
|
||||
this.headers = headers || null;
|
||||
this.httpMethod = httpMethod || null;
|
||||
};
|
||||
|
||||
module.exports = FileUploadOptions;
|
||||
|
||||
});
|
32
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
32
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* FileUploadResult
|
||||
* @constructor
|
||||
*/
|
||||
module.exports = function FileUploadResult(size, code, content) {
|
||||
this.bytesSent = size;
|
||||
this.responseCode = code;
|
||||
this.response = content;
|
||||
};
|
||||
});
|
327
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
327
platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec'),
|
||||
FileError = require('./FileError'),
|
||||
ProgressEvent = require('./ProgressEvent');
|
||||
|
||||
/**
|
||||
* This class writes to the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To write to the SD card, the file name is "sdcard/my_file.txt"
|
||||
*
|
||||
* @constructor
|
||||
* @param file {File} File object containing file properties
|
||||
* @param append if true write to the end of the file, otherwise overwrite the file
|
||||
*/
|
||||
var FileWriter = function(file) {
|
||||
this.fileName = "";
|
||||
this.length = 0;
|
||||
if (file) {
|
||||
this.localURL = file.localURL || file;
|
||||
this.length = file.size || 0;
|
||||
}
|
||||
// default is to write at the beginning of the file
|
||||
this.position = 0;
|
||||
|
||||
this.readyState = 0; // EMPTY
|
||||
|
||||
this.result = null;
|
||||
|
||||
// Error
|
||||
this.error = null;
|
||||
|
||||
// Event handlers
|
||||
this.onwritestart = null; // When writing starts
|
||||
this.onprogress = null; // While writing the file, and reporting partial file data
|
||||
this.onwrite = null; // When the write has successfully completed.
|
||||
this.onwriteend = null; // When the request has completed (either in success or failure).
|
||||
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
|
||||
this.onerror = null; // When the write has failed (see errors).
|
||||
};
|
||||
|
||||
// States
|
||||
FileWriter.INIT = 0;
|
||||
FileWriter.WRITING = 1;
|
||||
FileWriter.DONE = 2;
|
||||
|
||||
/**
|
||||
* Abort writing file.
|
||||
*/
|
||||
FileWriter.prototype.abort = function() {
|
||||
// check for invalid state
|
||||
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// set error
|
||||
this.error = new FileError(FileError.ABORT_ERR);
|
||||
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// If abort callback
|
||||
if (typeof this.onabort === "function") {
|
||||
this.onabort(new ProgressEvent("abort", {"target":this}));
|
||||
}
|
||||
|
||||
// If write end callback
|
||||
if (typeof this.onwriteend === "function") {
|
||||
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes data to the file
|
||||
*
|
||||
* @param data text or blob to be written
|
||||
* @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
|
||||
*/
|
||||
FileWriter.prototype.write = function(data, isPendingBlobReadResult) {
|
||||
|
||||
var that=this;
|
||||
var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
|
||||
var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
|
||||
var isBinary;
|
||||
|
||||
// Check to see if the incoming data is a blob
|
||||
if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function() {
|
||||
// Call this method again, with the arraybuffer as argument
|
||||
FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
|
||||
};
|
||||
fileReader.onerror = function () {
|
||||
// DONE state
|
||||
that.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
that.error = this.error;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof that.onerror === "function") {
|
||||
that.onerror(new ProgressEvent("error", {"target":that}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof that.onwriteend === "function") {
|
||||
that.onwriteend(new ProgressEvent("writeend", {"target":that}));
|
||||
}
|
||||
};
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
if (supportsBinary) {
|
||||
fileReader.readAsArrayBuffer(data);
|
||||
} else {
|
||||
fileReader.readAsText(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark data type for safer transport over the binary bridge
|
||||
isBinary = supportsBinary && (data instanceof ArrayBuffer);
|
||||
if (isBinary && cordova.platformId === "windowsphone") {
|
||||
// create a plain array, using the keys from the Uint8Array view so that we can serialize it
|
||||
data = Array.apply(null, new Uint8Array(data));
|
||||
}
|
||||
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// position always increases by bytes written because file would be extended
|
||||
me.position += r;
|
||||
// The length of the file is now where we are done writing.
|
||||
|
||||
me.length = me.position;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "write", [this.localURL, data, this.position, isBinary]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the file pointer to the location specified.
|
||||
*
|
||||
* If the offset is a negative number the position of the file
|
||||
* pointer is rewound. If the offset is greater than the file
|
||||
* size the position is set to the end of the file.
|
||||
*
|
||||
* @param offset is the location to move the file pointer to.
|
||||
*/
|
||||
FileWriter.prototype.seek = function(offset) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
if (!offset && offset !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See back from end of file.
|
||||
if (offset < 0) {
|
||||
this.position = Math.max(offset + this.length, 0);
|
||||
}
|
||||
// Offset is bigger than file size so set position
|
||||
// to the end of the file.
|
||||
else if (offset > this.length) {
|
||||
this.position = this.length;
|
||||
}
|
||||
// Offset is between 0 and file size so set the position
|
||||
// to start writing.
|
||||
else {
|
||||
this.position = offset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Truncates the file to the size specified.
|
||||
*
|
||||
* @param size to chop the file at.
|
||||
*/
|
||||
FileWriter.prototype.truncate = function(size) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw new FileError(FileError.INVALID_STATE_ERR);
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
|
||||
}
|
||||
|
||||
// Write file
|
||||
exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Update the length of the file
|
||||
me.length = r;
|
||||
me.position = Math.min(me.position, r);
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite(new ProgressEvent("write", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// Save error
|
||||
me.error = new FileError(e);
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror(new ProgressEvent("error", {"target":me}));
|
||||
}
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
|
||||
}
|
||||
}, "File", "truncate", [this.localURL, size]);
|
||||
};
|
||||
|
||||
module.exports = FileWriter;
|
||||
|
||||
});
|
39
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
39
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Flags.js
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supplies arguments to methods that lookup or create files and directories.
|
||||
*
|
||||
* @param create
|
||||
* {boolean} file or directory if it doesn't exist
|
||||
* @param exclusive
|
||||
* {boolean} used with create; if true the command will fail if
|
||||
* target path exists
|
||||
*/
|
||||
function Flags(create, exclusive) {
|
||||
this.create = create || false;
|
||||
this.exclusive = exclusive || false;
|
||||
}
|
||||
|
||||
module.exports = Flags;
|
||||
|
||||
});
|
26
platforms/ios/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
26
platforms/ios/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
exports.TEMPORARY = 0;
|
||||
exports.PERSISTENT = 1;
|
||||
|
||||
});
|
43
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
43
platforms/ios/platform_www/plugins/cordova-plugin-file/www/Metadata.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Information about the state of the file or directory
|
||||
*
|
||||
* {Date} modificationTime (readonly)
|
||||
*/
|
||||
var Metadata = function(metadata) {
|
||||
if (typeof metadata == "object") {
|
||||
this.modificationTime = new Date(metadata.modificationTime);
|
||||
this.size = metadata.size || 0;
|
||||
} else if (typeof metadata == "undefined") {
|
||||
this.modificationTime = null;
|
||||
this.size = 0;
|
||||
} else {
|
||||
/* Backwards compatiblity with platforms that only return a timestamp */
|
||||
this.modificationTime = new Date(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Metadata;
|
||||
|
||||
});
|
70
platforms/ios/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
70
platforms/ios/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
|
||||
// Feature test: See if we can instantiate a native ProgressEvent;
|
||||
// if so, use that approach,
|
||||
// otherwise fill-in with our own implementation.
|
||||
//
|
||||
// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
|
||||
var ProgressEvent = (function() {
|
||||
/*
|
||||
var createEvent = function(data) {
|
||||
var event = document.createEvent('Events');
|
||||
event.initEvent('ProgressEvent', false, false);
|
||||
if (data) {
|
||||
for (var i in data) {
|
||||
if (data.hasOwnProperty(i)) {
|
||||
event[i] = data[i];
|
||||
}
|
||||
}
|
||||
if (data.target) {
|
||||
// TODO: cannot call <some_custom_object>.dispatchEvent
|
||||
// need to first figure out how to implement EventTarget
|
||||
}
|
||||
}
|
||||
return event;
|
||||
};
|
||||
try {
|
||||
var ev = createEvent({type:"abort",target:document});
|
||||
return function ProgressEvent(type, data) {
|
||||
data.type = type;
|
||||
return createEvent(data);
|
||||
};
|
||||
} catch(e){
|
||||
*/
|
||||
return function ProgressEvent(type, dict) {
|
||||
this.type = type;
|
||||
this.bubbles = false;
|
||||
this.cancelBubble = false;
|
||||
this.cancelable = false;
|
||||
this.lengthComputable = false;
|
||||
this.loaded = dict && dict.loaded ? dict.loaded : 0;
|
||||
this.total = dict && dict.total ? dict.total : 0;
|
||||
this.target = dict && dict.target ? dict.target : null;
|
||||
};
|
||||
//}
|
||||
})();
|
||||
|
||||
module.exports = ProgressEvent;
|
||||
|
||||
});
|
29
platforms/ios/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
29
platforms/ios/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = function () {
|
||||
// window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and
|
||||
// possibly a good flag to indicate that we're running in Chrome
|
||||
return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
|
||||
};
|
||||
|
||||
});
|
66
platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
66
platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var channel = require('cordova/channel');
|
||||
|
||||
exports.file = {
|
||||
// Read-only directory where the application is installed.
|
||||
applicationDirectory: null,
|
||||
// Root of app's private writable storage
|
||||
applicationStorageDirectory: null,
|
||||
// Where to put app-specific data files.
|
||||
dataDirectory: null,
|
||||
// Cached files that should survive app restarts.
|
||||
// Apps should not rely on the OS to delete files in here.
|
||||
cacheDirectory: null,
|
||||
// Android: the application space on external storage.
|
||||
externalApplicationStorageDirectory: null,
|
||||
// Android: Where to put app-specific data files on external storage.
|
||||
externalDataDirectory: null,
|
||||
// Android: the application cache on external storage.
|
||||
externalCacheDirectory: null,
|
||||
// Android: the external storage (SD card) root.
|
||||
externalRootDirectory: null,
|
||||
// iOS: Temp directory that the OS can clear at will.
|
||||
tempDirectory: null,
|
||||
// iOS: Holds app-specific files that should be synced (e.g. to iCloud).
|
||||
syncedDataDirectory: null,
|
||||
// iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
|
||||
documentsDirectory: null,
|
||||
// BlackBerry10: Files globally available to all apps
|
||||
sharedDirectory: null
|
||||
};
|
||||
|
||||
channel.waitForInitialization('onFileSystemPathsReady');
|
||||
channel.onCordovaReady.subscribe(function() {
|
||||
function after(paths) {
|
||||
for (var k in paths) {
|
||||
exports.file[k] = paths[k];
|
||||
}
|
||||
channel.initializationComplete('onFileSystemPathsReady');
|
||||
}
|
||||
exec(after, null, 'File', 'requestAllPaths', []);
|
||||
});
|
||||
|
||||
|
||||
});
|
48
platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
48
platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Map of fsName -> FileSystem.
|
||||
var fsMap = null;
|
||||
var FileSystem = require('./FileSystem');
|
||||
var exec = require('cordova/exec');
|
||||
|
||||
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
|
||||
require('./fileSystems').getFs = function(name, callback) {
|
||||
function success(response) {
|
||||
fsMap = {};
|
||||
for (var i = 0; i < response.length; ++i) {
|
||||
var fsRoot = response[i];
|
||||
var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
|
||||
fsMap[fs.name] = fs;
|
||||
}
|
||||
callback(fsMap[name]);
|
||||
}
|
||||
|
||||
if (fsMap) {
|
||||
callback(fsMap[name]);
|
||||
} else {
|
||||
exec(success, null, "File", "requestAllFileSystems", []);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user