@@ -0,0 +1,179 @@
cordova.define("org.apache.cordova.contacts.Contact", 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'),
ContactError = require('./ContactError'),
utils = require('cordova/utils');

/**
* Converts primitives into Complex Object
* Currently only used for Date fields
*/
function convertIn(contact) {
var value = contact.birthday;
try {
contact.birthday = new Date(parseFloat(value));
} catch (exception){
console.log("Cordova Contact convertIn error: exception creating date.");
}
return contact;
}

/**
* Converts Complex objects into primitives
* Only conversion at present is for Dates.
**/

function convertOut(contact) {
var value = contact.birthday;
if (value !== null) {
// try to make it a Date object if it is not already
if (!utils.isDate(value)){
try {
value = new Date(value);
} catch(exception){
value = null;
}
}
if (utils.isDate(value)){
value = value.valueOf(); // convert to milliseconds
}
contact.birthday = value;
}
return contact;
}

/**
* Contains information about a single contact.
* @constructor
* @param {DOMString} id unique identifier
* @param {DOMString} displayName
* @param {ContactName} name
* @param {DOMString} nickname
* @param {Array.<ContactField>} phoneNumbers array of phone numbers
* @param {Array.<ContactField>} emails array of email addresses
* @param {Array.<ContactAddress>} addresses array of addresses
* @param {Array.<ContactField>} ims instant messaging user ids
* @param {Array.<ContactOrganization>} organizations
* @param {DOMString} birthday contact's birthday
* @param {DOMString} note user notes about contact
* @param {Array.<ContactField>} photos
* @param {Array.<ContactField>} categories
* @param {Array.<ContactField>} urls contact's web sites
*/
var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
ims, organizations, birthday, note, photos, categories, urls) {
this.id = id || null;
this.rawId = null;
this.displayName = displayName || null;
this.name = name || null; // ContactName
this.nickname = nickname || null;
this.phoneNumbers = phoneNumbers || null; // ContactField[]
this.emails = emails || null; // ContactField[]
this.addresses = addresses || null; // ContactAddress[]
this.ims = ims || null; // ContactField[]
this.organizations = organizations || null; // ContactOrganization[]
this.birthday = birthday || null;
this.note = note || null;
this.photos = photos || null; // ContactField[]
this.categories = categories || null; // ContactField[]
this.urls = urls || null; // ContactField[]
};

/**
* Removes contact from device storage.
* @param successCB success callback
* @param errorCB error callback
*/
Contact.prototype.remove = function(successCB, errorCB) {
argscheck.checkArgs('FF', 'Contact.remove', arguments);
var fail = errorCB && function(code) {
errorCB(new ContactError(code));
};
if (this.id === null) {
fail(ContactError.UNKNOWN_ERROR);
}
else {
exec(successCB, fail, "Contacts", "remove", [this.id]);
}
};

/**
* Creates a deep copy of this Contact.
* With the contact ID set to null.
* @return copy of this Contact
*/
Contact.prototype.clone = function() {
var clonedContact = utils.clone(this);
clonedContact.id = null;
clonedContact.rawId = null;

function nullIds(arr) {
if (arr) {
for (var i = 0; i < arr.length; ++i) {
arr[i].id = null;
}
}
}

// Loop through and clear out any id's in phones, emails, etc.
nullIds(clonedContact.phoneNumbers);
nullIds(clonedContact.emails);
nullIds(clonedContact.addresses);
nullIds(clonedContact.ims);
nullIds(clonedContact.organizations);
nullIds(clonedContact.categories);
nullIds(clonedContact.photos);
nullIds(clonedContact.urls);
return clonedContact;
};

/**
* Persists contact to device storage.
* @param successCB success callback
* @param errorCB error callback
*/
Contact.prototype.save = function(successCB, errorCB) {
argscheck.checkArgs('FFO', 'Contact.save', arguments);
var fail = errorCB && function(code) {
errorCB(new ContactError(code));
};
var success = function(result) {
if (result) {
if (successCB) {
var fullContact = require('./contacts').create(result);
successCB(convertIn(fullContact));
}
}
else {
// no Entry object returned
fail(ContactError.UNKNOWN_ERROR);
}
};
var dupContact = convertOut(utils.clone(this));
exec(success, fail, "Contacts", "save", [dupContact]);
};


module.exports = Contact;

});
@@ -0,0 +1,48 @@
cordova.define("org.apache.cordova.contacts.ContactAddress", 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.
*
*/

/**
* Contact address.
* @constructor
* @param {DOMString} id unique identifier, should only be set by native code
* @param formatted // NOTE: not a W3C standard
* @param streetAddress
* @param locality
* @param region
* @param postalCode
* @param country
*/

var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) {
this.id = null;
this.pref = (typeof pref != 'undefined' ? pref : false);
this.type = type || null;
this.formatted = formatted || null;
this.streetAddress = streetAddress || null;
this.locality = locality || null;
this.region = region || null;
this.postalCode = postalCode || null;
this.country = country || null;
};

module.exports = ContactAddress;

});
@@ -0,0 +1,44 @@
cordova.define("org.apache.cordova.contacts.ContactError", 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.
*
*/

/**
* ContactError.
* An error code assigned by an implementation when an error has occurred
* @constructor
*/
var ContactError = function(err) {
this.code = (typeof err != 'undefined' ? err : null);
};

/**
* Error codes
*/
ContactError.UNKNOWN_ERROR = 0;
ContactError.INVALID_ARGUMENT_ERROR = 1;
ContactError.TIMEOUT_ERROR = 2;
ContactError.PENDING_OPERATION_ERROR = 3;
ContactError.IO_ERROR = 4;
ContactError.NOT_SUPPORTED_ERROR = 5;
ContactError.PERMISSION_DENIED_ERROR = 20;

module.exports = ContactError;

});
@@ -0,0 +1,39 @@
cordova.define("org.apache.cordova.contacts.ContactField", 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.
*
*/

/**
* Generic contact field.
* @constructor
* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
* @param type
* @param value
* @param pref
*/
var ContactField = function(type, value, pref) {
this.id = null;
this.type = (type && type.toString()) || null;
this.value = (value && value.toString()) || null;
this.pref = (typeof pref != 'undefined' ? pref : false);
};

module.exports = ContactField;

});
@@ -0,0 +1,57 @@
cordova.define("org.apache.cordova.contacts.ContactFieldType", 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.
*
*/

// Possible field names for various platforms.
// Some field names are platform specific

var fieldType = {
addresses: "addresses",
birthday: "birthday",
categories: "categories",
country: "country",
department: "department",
displayName: "displayName",
emails: "emails",
familyName: "familyName",
formatted: "formatted",
givenName: "givenName",
honorificPrefix: "honorificPrefix",
honorificSuffix: "honorificSuffix",
id: "id",
ims: "ims",
locality: "locality",
middleName: "middleName",
name: "name",
nickname: "nickname",
note: "note",
organizations: "organizations",
phoneNumbers: "phoneNumbers",
photos: "photos",
postalCode: "postalCode",
region: "region",
streetAddress: "streetAddress",
title: "title",
urls: "urls"
};

module.exports = fieldType;

});
@@ -0,0 +1,37 @@
cordova.define("org.apache.cordova.contacts.ContactFindOptions", 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.
*
*/

/**
* ContactFindOptions.
* @constructor
* @param filter used to match contacts against
* @param multiple boolean used to determine if more than one contact should be returned
*/

var ContactFindOptions = function(filter, multiple, desiredFields) {
this.filter = filter || '';
this.multiple = (typeof multiple != 'undefined' ? multiple : false);
this.desiredFields = typeof desiredFields != 'undefined' ? desiredFields : [];
};

module.exports = ContactFindOptions;

});
@@ -0,0 +1,43 @@
cordova.define("org.apache.cordova.contacts.ContactName", 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.
*
*/

/**
* Contact name.
* @constructor
* @param formatted // NOTE: not part of W3C standard
* @param familyName
* @param givenName
* @param middle
* @param prefix
* @param suffix
*/
var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) {
this.formatted = formatted || null;
this.familyName = familyName || null;
this.givenName = givenName || null;
this.middleName = middle || null;
this.honorificPrefix = prefix || null;
this.honorificSuffix = suffix || null;
};

module.exports = ContactName;

});
@@ -0,0 +1,43 @@
cordova.define("org.apache.cordova.contacts.ContactOrganization", 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.
*
*/

/**
* Contact organization.
* @constructor
* @param pref
* @param type
* @param name
* @param dept
* @param title
*/

var ContactOrganization = function(pref, type, name, dept, title) {
this.id = null;
this.pref = (typeof pref != 'undefined' ? pref : false);
this.type = type || null;
this.name = name || null;
this.department = dept || null;
this.title = title || null;
};

module.exports = ContactOrganization;

});
@@ -0,0 +1,100 @@
cordova.define("org.apache.cordova.contacts.contacts", 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'),
ContactError = require('./ContactError'),
utils = require('cordova/utils'),
Contact = require('./Contact'),
fieldType = require('./ContactFieldType');


/**
* Represents a group of Contacts.
* @constructor
*/
var contacts = {
fieldType: fieldType,
/**
* Returns an array of Contacts matching the search criteria.
* @param fields that should be searched
* @param successCB success callback
* @param errorCB error callback
* @param {ContactFindOptions} options that can be applied to contact searching
* @return array of Contacts matching search criteria
*/
find:function(fields, successCB, errorCB, options) {
argscheck.checkArgs('afFO', 'contacts.find', arguments);
if (!fields.length) {
errorCB && errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
} else {
// missing 'options' param means return all contacts
options = options || {filter: '', multiple: true}
var win = function(result) {
var cs = [];
for (var i = 0, l = result.length; i < l; i++) {
cs.push(contacts.create(result[i]));
}
successCB(cs);
};
exec(win, errorCB, "Contacts", "search", [fields, options]);
}
},

/**
* This function picks contact from phone using contact picker UI
* @returns new Contact object
*/
pickContact: function (successCB, errorCB) {

argscheck.checkArgs('fF', 'contacts.pick', arguments);

var win = function (result) {
// if Contacts.pickContact return instance of Contact object
// don't create new Contact object, use current
var contact = result instanceof Contact ? result : contacts.create(result);
successCB(contact);
};
exec(win, errorCB, "Contacts", "pickContact", []);
},

/**
* This function creates a new contact, but it does not persist the contact
* to device storage. To persist the contact to device storage, invoke
* contact.save().
* @param properties an object whose properties will be examined to create a new Contact
* @returns new Contact object
*/
create:function(properties) {
argscheck.checkArgs('O', 'contacts.create', arguments);
var contact = new Contact();
for (var i in properties) {
if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
contact[i] = properties[i];
}
}
return contact;
}
};

module.exports = contacts;

});
@@ -0,0 +1,31 @@
cordova.define("org.apache.cordova.device-motion.Acceleration", 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 Acceleration = function(x, y, z, timestamp) {
this.x = x;
this.y = y;
this.z = z;
this.timestamp = timestamp || (new Date()).getTime();
};

module.exports = Acceleration;

});
@@ -0,0 +1,171 @@
cordova.define("org.apache.cordova.device-motion.accelerometer", 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.
*
*/

/**
* This class provides access to device accelerometer data.
* @constructor
*/
var argscheck = require('cordova/argscheck'),
utils = require("cordova/utils"),
exec = require("cordova/exec"),
Acceleration = require('./Acceleration');

// Is the accel sensor running?
var running = false;

// Keeps reference to watchAcceleration calls.
var timers = {};

// Array of listeners; used to keep track of when we should call start and stop.
var listeners = [];

// Last returned acceleration object from native
var accel = null;

// Tells native to start.
function start() {
exec(function(a) {
var tempListeners = listeners.slice(0);
accel = new Acceleration(a.x, a.y, a.z, a.timestamp);
for (var i = 0, l = tempListeners.length; i < l; i++) {
tempListeners[i].win(accel);
}
}, function(e) {
var tempListeners = listeners.slice(0);
for (var i = 0, l = tempListeners.length; i < l; i++) {
tempListeners[i].fail(e);
}
}, "Accelerometer", "start", []);
running = true;
}

// Tells native to stop.
function stop() {
exec(null, null, "Accelerometer", "stop", []);
running = false;
}

// Adds a callback pair to the listeners array
function createCallbackPair(win, fail) {
return {win:win, fail:fail};
}

// Removes a win/fail listener pair from the listeners array
function removeListeners(l) {
var idx = listeners.indexOf(l);
if (idx > -1) {
listeners.splice(idx, 1);
if (listeners.length === 0) {
stop();
}
}
}

var accelerometer = {
/**
* Asynchronously acquires the current acceleration.
*
* @param {Function} successCallback The function to call when the acceleration data is available
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
*/
getCurrentAcceleration: function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.getCurrentAcceleration', arguments);

var p;
var win = function(a) {
removeListeners(p);
successCallback(a);
};
var fail = function(e) {
removeListeners(p);
errorCallback && errorCallback(e);
};

p = createCallbackPair(win, fail);
listeners.push(p);

if (!running) {
start();
}
},

/**
* Asynchronously acquires the acceleration repeatedly at a given interval.
*
* @param {Function} successCallback The function to call each time the acceleration data is available
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
* @return String The watch id that must be passed to #clearWatch to stop watching.
*/
watchAcceleration: function(successCallback, errorCallback, options) {
argscheck.checkArgs('fFO', 'accelerometer.watchAcceleration', arguments);
// Default interval (10 sec)
var frequency = (options && options.frequency && typeof options.frequency == 'number') ? options.frequency : 10000;

// Keep reference to watch id, and report accel readings as often as defined in frequency
var id = utils.createUUID();

var p = createCallbackPair(function(){}, function(e) {
removeListeners(p);
errorCallback && errorCallback(e);
});
listeners.push(p);

timers[id] = {
timer:window.setInterval(function() {
if (accel) {
successCallback(accel);
}
}, frequency),
listeners:p
};

if (running) {
// If we're already running then immediately invoke the success callback
// but only if we have retrieved a value, sample code does not check for null ...
if (accel) {
successCallback(accel);
}
} else {
start();
}

return id;
},

/**
* Clears the specified accelerometer watch.
*
* @param {String} id The id of the watch returned from #watchAcceleration.
*/
clearWatch: function(id) {
// Stop javascript timer & remove from timer list
if (id && timers[id]) {
window.clearInterval(timers[id].timer);
removeListeners(timers[id].listeners);
delete timers[id];
}
}
};
module.exports = accelerometer;

});
@@ -0,0 +1,81 @@
cordova.define("org.apache.cordova.device.device", 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'),
channel = require('cordova/channel'),
utils = require('cordova/utils'),
exec = require('cordova/exec'),
cordova = require('cordova');

channel.createSticky('onCordovaInfoReady');
// Tell cordova channel to wait on the CordovaInfoReady event
channel.waitForInitialization('onCordovaInfoReady');

/**
* This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
* phone, etc.
* @constructor
*/
function Device() {
this.available = false;
this.platform = null;
this.version = null;
this.uuid = null;
this.cordova = null;
this.model = null;
this.manufacturer = null;

var me = this;

channel.onCordovaReady.subscribe(function() {
me.getInfo(function(info) {
//ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
//TODO: CB-5105 native implementations should not return info.cordova
var buildLabel = cordova.version;
me.available = true;
me.platform = info.platform;
me.version = info.version;
me.uuid = info.uuid;
me.cordova = buildLabel;
me.model = info.model;
me.manufacturer = info.manufacturer || 'unknown';
channel.onCordovaInfoReady.fire();
},function(e) {
me.available = false;
utils.alert("[ERROR] Error initializing Cordova: " + e);
});
});
}

/**
* Get device info
*
* @param {Function} successCallback The function to call when the heading data is available
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
*/
Device.prototype.getInfo = function(successCallback, errorCallback) {
argscheck.checkArgs('fF', 'Device.getInfo', arguments);
exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
};

module.exports = new Device();

});
@@ -0,0 +1,76 @@
cordova.define("org.apache.cordova.dialogs.notification_android", 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');

/**
* Provides Android enhanced notification API.
*/
module.exports = {
activityStart : function(title, message) {
// If title and message not specified then mimic Android behavior of
// using default strings.
if (typeof title === "undefined" && typeof message == "undefined") {
title = "Busy";
message = 'Please wait...';
}

exec(null, null, 'Notification', 'activityStart', [ title, message ]);
},

/**
* Close an activity dialog
*/
activityStop : function() {
exec(null, null, 'Notification', 'activityStop', []);
},

/**
* Display a progress dialog with progress bar that goes from 0 to 100.
*
* @param {String}
* title Title of the progress dialog.
* @param {String}
* message Message to display in the dialog.
*/
progressStart : function(title, message) {
exec(null, null, 'Notification', 'progressStart', [ title, message ]);
},

/**
* Close the progress dialog.
*/
progressStop : function() {
exec(null, null, 'Notification', 'progressStop', []);
},

/**
* Set the progress dialog value.
*
* @param {Number}
* value 0-100
*/
progressValue : function(value) {
exec(null, null, 'Notification', 'progressValue', [ value ]);
}
};

});
@@ -0,0 +1,114 @@
cordova.define("org.apache.cordova.dialogs.notification", 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 platform = require('cordova/platform');

/**
* Provides access to notifications on the device.
*/

module.exports = {

/**
* Open a native alert dialog, with a customizable title and button text.
*
* @param {String} message Message to print in the body of the alert
* @param {Function} completeCallback The callback that is called when user clicks on a button.
* @param {String} title Title of the alert dialog (default: Alert)
* @param {String} buttonLabel Label of the close button (default: OK)
*/
alert: function(message, completeCallback, title, buttonLabel) {
var _title = (title || "Alert");
var _buttonLabel = (buttonLabel || "OK");
exec(completeCallback, null, "Notification", "alert", [message, _title, _buttonLabel]);
},

/**
* Open a native confirm dialog, with a customizable title and button text.
* The result that the user selects is returned to the result callback.
*
* @param {String} message Message to print in the body of the alert
* @param {Function} resultCallback The callback that is called when user clicks on a button.
* @param {String} title Title of the alert dialog (default: Confirm)
* @param {Array} buttonLabels Array of the labels of the buttons (default: ['OK', 'Cancel'])
*/
confirm: function(message, resultCallback, title, buttonLabels) {
var _title = (title || "Confirm");
var _buttonLabels = (buttonLabels || ["OK", "Cancel"]);

// Strings are deprecated!
if (typeof _buttonLabels === 'string') {
console.log("Notification.confirm(string, function, string, string) is deprecated. Use Notification.confirm(string, function, string, array).");
}

// Some platforms take an array of button label names.
// Other platforms take a comma separated list.
// For compatibility, we convert to the desired type based on the platform.
if (platform.id == "amazon-fireos" || platform.id == "android" || platform.id == "ios" ||
platform.id == "windowsphone" || platform.id == "firefoxos" || platform.id == "ubuntu" ||
platform.id == "windows8" || platform.id == "windows") {

if (typeof _buttonLabels === 'string') {
_buttonLabels = _buttonLabels.split(","); // not crazy about changing the var type here
}
} else {
if (Array.isArray(_buttonLabels)) {
var buttonLabelArray = _buttonLabels;
_buttonLabels = buttonLabelArray.toString();
}
}
exec(resultCallback, null, "Notification", "confirm", [message, _title, _buttonLabels]);
},

/**
* Open a native prompt dialog, with a customizable title and button text.
* The following results are returned to the result callback:
* buttonIndex Index number of the button selected.
* input1 The text entered in the prompt dialog box.
*
* @param {String} message Dialog message to display (default: "Prompt message")
* @param {Function} resultCallback The callback that is called when user clicks on a button.
* @param {String} title Title of the dialog (default: "Prompt")
* @param {Array} buttonLabels Array of strings for the button labels (default: ["OK","Cancel"])
* @param {String} defaultText Textbox input value (default: empty string)
*/
prompt: function(message, resultCallback, title, buttonLabels, defaultText) {
var _message = (message || "Prompt message");
var _title = (title || "Prompt");
var _buttonLabels = (buttonLabels || ["OK","Cancel"]);
var _defaultText = (defaultText || "");
exec(resultCallback, null, "Notification", "prompt", [_message, _title, _buttonLabels, _defaultText]);
},

/**
* Causes the device to beep.
* On Android, the default notification ringtone is played "count" times.
*
* @param {Integer} count The number of beeps.
*/
beep: function(count) {
var defaultedCount = count || 1;
exec(null, null, "Notification", "beep", [ defaultedCount ]);
}
};

});
@@ -0,0 +1,214 @@
cordova.define("org.apache.cordova.file-transfer.FileTransfer", 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'),
FileTransferError = require('./FileTransferError'),
ProgressEvent = require('org.apache.cordova.file.ProgressEvent');

function newProgressEvent(result) {
var pe = new ProgressEvent();
pe.lengthComputable = result.lengthComputable;
pe.loaded = result.loaded;
pe.total = result.total;
return pe;
}

function getUrlCredentials(urlString) {
var credentialsPattern = /^https?\:\/\/(?:(?:(([^:@\/]*)(?::([^@\/]*))?)?@)?([^:\/?#]*)(?::(\d*))?).*$/,
credentials = credentialsPattern.exec(urlString);

return credentials && credentials[1];
}

function getBasicAuthHeader(urlString) {
var header = null;


// This is changed due to MS Windows doesn't support credentials in http uris
// so we detect them by regexp and strip off from result url
// Proof: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/a327cf3c-f033-4a54-8b7f-03c56ba3203f/windows-foundation-uri-security-problem

if (window.btoa) {
var credentials = getUrlCredentials(urlString);
if (credentials) {
var authHeader = "Authorization";
var authHeaderValue = "Basic " + window.btoa(credentials);

header = {
name : authHeader,
value : authHeaderValue
};
}
}

return header;
}

var idCounter = 0;

/**
* FileTransfer uploads a file to a remote server.
* @constructor
*/
var FileTransfer = function() {
this._id = ++idCounter;
this.onprogress = null; // optional callback
};

/**
* Given an absolute file path, uploads a file on the device to a remote server
* using a multipart HTTP request.
* @param filePath {String} Full path of the file on the device
* @param server {String} URL of the server to receive the file
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
* @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
*/
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) {
argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments);
// check for options
var fileKey = null;
var fileName = null;
var mimeType = null;
var params = null;
var chunkedMode = true;
var headers = null;
var httpMethod = null;
var basicAuthHeader = getBasicAuthHeader(server);
if (basicAuthHeader) {
server = server.replace(getUrlCredentials(server) + '@', '');

options = options || {};
options.headers = options.headers || {};
options.headers[basicAuthHeader.name] = basicAuthHeader.value;
}

if (options) {
fileKey = options.fileKey;
fileName = options.fileName;
mimeType = options.mimeType;
headers = options.headers;
httpMethod = options.httpMethod || "POST";
if (httpMethod.toUpperCase() == "PUT"){
httpMethod = "PUT";
} else {
httpMethod = "POST";
}
if (options.chunkedMode !== null || typeof options.chunkedMode != "undefined") {
chunkedMode = options.chunkedMode;
}
if (options.params) {
params = options.params;
}
else {
params = {};
}
}

var fail = errorCallback && function(e) {
var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception);
errorCallback(error);
};

var self = this;
var win = function(result) {
if (typeof result.lengthComputable != "undefined") {
if (self.onprogress) {
self.onprogress(newProgressEvent(result));
}
} else {
successCallback && successCallback(result);
}
};
exec(win, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
};

/**
* Downloads a file form a given URL and saves it to the specified directory.
* @param source {String} URL of the server to receive the file
* @param target {String} Full path of the file on the device
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
* @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
* @param options {FileDownloadOptions} Optional parameters such as headers
*/
FileTransfer.prototype.download = function(source, target, successCallback, errorCallback, trustAllHosts, options) {
argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments);
var self = this;

var basicAuthHeader = getBasicAuthHeader(source);
if (basicAuthHeader) {
source = source.replace(getUrlCredentials(source) + '@', '');

options = options || {};
options.headers = options.headers || {};
options.headers[basicAuthHeader.name] = basicAuthHeader.value;
}

var headers = null;
if (options) {
headers = options.headers || null;
}

var win = function(result) {
if (typeof result.lengthComputable != "undefined") {
if (self.onprogress) {
return self.onprogress(newProgressEvent(result));
}
} else if (successCallback) {
var entry = null;
if (result.isDirectory) {
entry = new (require('org.apache.cordova.file.DirectoryEntry'))();
}
else if (result.isFile) {
entry = new (require('org.apache.cordova.file.FileEntry'))();
}
entry.isDirectory = result.isDirectory;
entry.isFile = result.isFile;
entry.name = result.name;
entry.fullPath = result.fullPath;
entry.filesystem = new FileSystem(result.filesystemName || (result.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
entry.nativeURL = result.nativeURL;
successCallback(entry);
}
};

var fail = errorCallback && function(e) {
var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception);
errorCallback(error);
};

exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id, headers]);
};

/**
* Aborts the ongoing file transfer on this object. The original error
* callback for the file transfer will be called if necessary.
*/
FileTransfer.prototype.abort = function() {
exec(null, null, 'FileTransfer', 'abort', [this._id]);
};

module.exports = FileTransfer;

});
@@ -0,0 +1,43 @@
cordova.define("org.apache.cordova.file-transfer.FileTransferError", 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.
*
*/

/**
* FileTransferError
* @constructor
*/
var FileTransferError = function(code, source, target, status, body, exception) {
this.code = code || null;
this.source = source || null;
this.target = target || null;
this.http_status = status || null;
this.body = body || null;
this.exception = exception || null;
};

FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
FileTransferError.ABORT_ERR = 4;
FileTransferError.NOT_MODIFIED_ERR = 5;

module.exports = FileTransferError;

});
@@ -0,0 +1,119 @@
cordova.define("org.apache.cordova.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;

});
@@ -0,0 +1,75 @@
cordova.define("org.apache.cordova.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;

});
@@ -0,0 +1,256 @@
cordova.define("org.apache.cordova.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 result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, parent.filesystem, entry.nativeURL) : new (require('org.apache.cordova.file.FileEntry'))(entry.name, entry.fullPath, parent.filesystem, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
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 result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, parent.filesystem, entry.nativeURL) : new (require('org.apache.cordova.file.FileEntry'))(entry.name, entry.fullPath, parent.filesystem, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
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);
}
};

/**
* 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;

});
@@ -0,0 +1,81 @@
cordova.define("org.apache.cordova.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;

});
@@ -0,0 +1,83 @@
cordova.define("org.apache.cordova.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) {
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 === "") {
errorCallback && errorCallback(new FileError(FileError.INVALID_STATE_ERR));
} else {
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;

});
@@ -0,0 +1,48 @@
cordova.define("org.apache.cordova.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;

});
@@ -0,0 +1,389 @@
cordova.define("org.apache.cordova.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'),
File = require('./File'),
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._localURL = '';
this._realReader = origFileReader ? new origFileReader() : {};
};

// 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._readyState = FileReader.LOADING;

if (typeof file.localURL == 'string') {
reader._localURL = file.localURL;
} else {
reader._localURL = '';
return true;
}

reader.onloadstart && reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
}

/**
* 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 me = this;
var execArgs = [this._localURL, enc, file.start, file.end];

// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

// Save result
me._result = r;

// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

// null result
me._result = null;

// Save error
me._error = new FileError(e);

// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsText", execArgs);
};


/**
* 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 me = this;
var execArgs = [this._localURL, file.start, file.end];

// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

// Save result
me._result = r;

// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

me._result = null;

// Save error
me._error = new FileError(e);

// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsDataURL", execArgs);
};

/**
* 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 me = this;
var execArgs = [this._localURL, file.start, file.end];

// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

me._result = r;

// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

me._result = null;

// Save error
me._error = new FileError(e);

// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsBinaryString", execArgs);
};

/**
* 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 me = this;
var execArgs = [this._localURL, file.start, file.end];

// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

me._result = r;

// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}

// DONE state
me._readyState = FileReader.DONE;

me._result = null;

// Save error
me._error = new FileError(e);

// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}

// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsArrayBuffer", execArgs);
};

module.exports = FileReader;

});
@@ -0,0 +1,50 @@
cordova.define("org.apache.cordova.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) {
return fullPath;
};

FileSystem.prototype.toJSON = function() {
return "<FileSystem: " + this.name + ">";
};

module.exports = FileSystem;

});
@@ -0,0 +1,43 @@
cordova.define("org.apache.cordova.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;

});
@@ -0,0 +1,31 @@
cordova.define("org.apache.cordova.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;
};
});
@@ -0,0 +1,304 @@
cordova.define("org.apache.cordova.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
*/
FileWriter.prototype.write = function(data) {

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);
};
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) {
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;

});
@@ -0,0 +1,38 @@
cordova.define("org.apache.cordova.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;

});