[sword-svn] r3509 - in trunk/bindings: . cordova cordova/org.crosswire.sword.cordova.SWORD cordova/org.crosswire.sword.cordova.SWORD/doc cordova/org.crosswire.sword.cordova.SWORD/src cordova/org.crosswire.sword.cordova.SWORD/src/android cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10 cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos cordova/org.crosswire.sword.cordova.SWORD/src/ios cordova/org.crosswire.sword.cordova.SWORD/src/tizen cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu cordova/org.crosswire.sword.cordova.SWORD/src/windows8 cordova/org.crosswire.sword.cordova.SWORD/src/wp cordova/org.crosswire.sword.cordova.SWORD/www

scribe at crosswire.org scribe at crosswire.org
Wed Nov 1 03:37:19 MST 2017


Author: scribe
Date: 2017-11-01 03:37:19 -0700 (Wed, 01 Nov 2017)
New Revision: 3509

Added:
   trunk/bindings/cordova/
   trunk/bindings/cordova/Makefile
   trunk/bindings/cordova/README
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/LICENSE
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/README.md
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/RELEASENOTES.md
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/doc/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/doc/index.md
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/package.json
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/plugin.xml
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/android/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/android/SWORD.java
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10/index.js
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos/DeviceProxy.js
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.h
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.m
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/tizen/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/tizen/DeviceProxy.js
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.cpp
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.h
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.js
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/windows8/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/windows8/DeviceProxy.js
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/wp/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/wp/Device.cs
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/www/
   trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/www/SWORD.js
Log:
Added new binding/cordova plugin which only works on Android currently and has other template files still in place which still need to removed or rewritten

Added: trunk/bindings/cordova/Makefile
===================================================================
--- trunk/bindings/cordova/Makefile	                        (rev 0)
+++ trunk/bindings/cordova/Makefile	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,10 @@
+all:
+	@echo
+	@echo "native binary component is built from ../Android/"
+	@echo
+
+clean:
+	# these are from ../Android
+	rm -rf org.crosswire.sword.cordova.SWORD/libs/android/*
+	rm org.crosswire.sword.cordova.SWORD/src/android/AndroidMgr.java org.crosswire.sword.cordova.SWORD/src/android/InstallMgr.java org.crosswire.sword.cordova.SWORD/src/android/SWMgr.java org.crosswire.sword.cordova.SWORD/src/android/SWModule.java
+

Added: trunk/bindings/cordova/README
===================================================================
--- trunk/bindings/cordova/README	                        (rev 0)
+++ trunk/bindings/cordova/README	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,5 @@
+This folder contains a cordova plugin which is based on the
+../Android bindings which is based on the java-jni/ bindings.
+
+Follow the README in the ../java-jni/ bindings folder.
+

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/LICENSE
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/LICENSE	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/LICENSE	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/README.md
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/README.md	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/README.md	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,22 @@
+<!---
+ license: 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.
+-->
+
+# org.apache.cordova.device
+
+Plugin documentation: [doc/index.md](doc/index.md)

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/RELEASENOTES.md
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/RELEASENOTES.md	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/RELEASENOTES.md	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,57 @@
+<!--
+#
+# 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.
+#
+-->
+# Release Notes
+
+### 0.2.1 (Sept 5, 2013)
+* removed extraneous print statement
+* [CB-4432] copyright notice change
+
+### 0.2.3 (Sept 25, 2013)
+* CB-4889 bumping&resetting version
+* [windows8] commandProxy has moved
+* [BlackBerry10] removed uneeded permission tags in plugin.xml
+* CB-4889 renaming org.apache.cordova.core.device to org.apache.cordova.device
+* Rename CHANGELOG.md -> RELEASENOTES.md
+* updated to use commandProxy for ffos
+* add firefoxos support
+* [CB-4752] Incremented plugin version on dev branch. 
+
+### 0.2.4 (Oct 28, 2013)
+* CB-5128: added repo + issue tag in plugin.xml for device plugin
+* CB-5085 device.cordova returning wrong value
+* [CB-4915] Incremented plugin version on dev branch.
+
+### 0.2.5 (Dec 4, 2013)
+* CB-5316 Spell Cordova as a brand unless it's a command or script
+* [ubuntu] use cordova/exec/proxy
+* add ubuntu platform
+* Modify Device.platform logic to use amazon-fireos as the platform for Amazon Devices
+* 1. Added amazon-fireos platform. 2. Change to use cordova-amazon-fireos as the platform if user agent contains 'cordova-amazon-fireos'
+
+### 0.2.6 (Jan 02, 2014)
+* CB-5658 Add doc/index.md for Device plugin
+* CB-5504 Moving Telephony Logic out of Device
+
+### 0.2.7 (Jan 07, 2014)
+* CB-5737 Fix exception on close caused by left over telephony code from CB-5504
+
+### 0.2.8 (Feb 05, 2014)
+* Tizen support added

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/doc/index.md
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/doc/index.md	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/doc/index.md	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,213 @@
+<!---
+    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.
+-->
+
+# org.apache.cordova.device
+
+This plugin defines a global `device` object, which describes the device's hardware and software.
+Although the object is in the global scope, it is not available until after the `deviceready` event.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(device.cordova);
+    }
+
+## Installation
+
+    cordova plugin add org.apache.cordova.device
+
+## Properties
+
+- device.cordova
+- device.model
+- device.name
+- device.platform
+- device.uuid
+- device.version
+
+## device.cordova
+
+Get the version of Cordova running on the device.
+
+### Supported Platforms
+
+- Amazon Fire OS
+- Android
+- BlackBerry 10
+- Firefox OS
+- iOS
+- Tizen
+- Windows Phone 7 and 8
+- Windows 8
+
+## device.model
+
+The `device.model` returns the name of the device's model or
+product. The value is set by the device manufacturer and may be
+different across versions of the same product.
+
+### Supported Platforms
+
+- Android
+- BlackBerry 10
+- iOS
+- Tizen
+- Windows Phone 7 and 8
+- Windows 8
+
+### Quick Example
+
+    // Android:    Nexus One       returns "Passion" (Nexus One code name)
+    //             Motorola Droid  returns "voles"
+    // BlackBerry: Torch 9800      returns "9800"
+    // iOS:     for the iPad Mini, returns iPad2,5; iPhone 5 is iPhone 5,1. See http://theiphonewiki.com/wiki/index.php?title=Models
+    //
+    var model = device.model;
+
+### Android Quirks
+
+- Gets the [product name](http://developer.android.com/reference/android/os/Build.html#PRODUCT) instead of the [model name](http://developer.android.com/reference/android/os/Build.html#MODEL), which is often the production code name. For example, the Nexus One returns `Passion`, and Motorola Droid returns `voles`.
+
+### Tizen Quirks
+
+- Returns the device model assigned by the vendor, for example, `TIZEN`
+
+### Windows Phone 7 and 8 Quirks
+
+- Returns the device model specified by the manufacturer. For example, the Samsung Focus returns `SGH-i917`.
+
+## device.name
+
+__WARNING__: `device.name` is deprecated as of version 2.3.0. Use `device.model` instead.
+
+## device.platform
+
+Get the device's operating system name.
+
+    var string = device.platform;
+
+### Supported Platforms
+
+- Android
+- BlackBerry 10
+- Firefox OS
+- iOS
+- Tizen
+- Windows Phone 7 and 8
+- Windows 8
+
+### Quick Example
+
+    // Depending on the device, a few examples are:
+    //   - "Android"
+    //   - "BlackBerry 10"
+    //   - "iOS"
+    //   - "WinCE"
+    //   - "Tizen"
+    var devicePlatform = device.platform;
+
+### Windows Phone 7 Quirks
+
+Windows Phone 7 devices report the platform as `WinCE`.
+
+### Windows Phone 8 Quirks
+
+Windows Phone 8 devices report the platform as `Win32NT`.
+
+## device.uuid
+
+Get the device's Universally Unique Identifier ([UUID](http://en.wikipedia.org/wiki/Universally_Unique_Identifier)).
+
+    var string = device.uuid;
+
+### Description
+
+The details of how a UUID is generated are determined by the device manufacturer and are specific to the device's platform or model.
+
+### Supported Platforms
+
+- Android
+- BlackBerry 10
+- iOS
+- Tizen
+- Windows Phone 7 and 8
+- Windows 8
+
+### Quick Example
+
+    // Android: Returns a random 64-bit integer (as a string, again!)
+    //          The integer is generated on the device's first boot
+    //
+    // BlackBerry: Returns the PIN number of the device
+    //             This is a nine-digit unique integer (as a string, though!)
+    //
+    // iPhone: (Paraphrased from the UIDevice Class documentation)
+    //         Returns a string of hash values created from multiple hardware identifies.
+    //         It is guaranteed to be unique for every device and can't be tied
+    //         to the user account.
+    // Windows Phone 7 : Returns a hash of device+current user,
+    // if the user is not defined, a guid is generated and will persist until the app is uninstalled
+    // Tizen: returns the device IMEI (International Mobile Equipment Identity or IMEI is a number
+    // unique to every GSM and UMTS mobile phone.
+    var deviceID = device.uuid;
+
+### iOS Quirk
+
+The `uuid` on iOS is not unique to a device, but varies for each
+application, for each installation.  It changes if you delete and
+re-install the app, and possibly also when you upgrade iOS, or even
+upgrade the app per version (apparent in iOS 5.1). The `uuid` is not
+a reliable value.
+
+### Windows Phone 7 and 8 Quirks
+
+The `uuid` for Windows Phone 7 requires the permission
+`ID_CAP_IDENTITY_DEVICE`.  Microsoft will likely deprecate this
+property soon.  If the capability is not available, the application
+generates a persistent guid that is maintained for the duration of the
+application's installation on the device.
+
+## device.version
+
+Get the operating system version.
+
+    var string = device.version;
+
+### Supported Platforms
+
+- Android 2.1+
+- BlackBerry 10
+- iOS
+- Tizen
+- Windows Phone 7 and 8
+- Windows 8
+
+### Quick Example
+
+    // Android:    Froyo OS would return "2.2"
+    //             Eclair OS would return "2.1", "2.0.1", or "2.0"
+    //             Version can also return update level "2.1-update1"
+    //
+    // BlackBerry: Torch 9800 using OS 6.0 would return "6.0.0.600"
+    //
+    // iPhone:     iOS 3.2 returns "3.2"
+    //
+    // Windows Phone 7: returns current OS version number, ex. on Mango returns 7.10.7720
+    // Tizen: returns "TIZEN_20120425_2"
+    var deviceVersion = device.version;
+

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/package.json
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/package.json	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/package.json	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,26 @@
+{
+  "name": "SWORD",
+  "version": "0.0.1",
+  "description": "The SWORD Project Plugin",
+  "cordova": {
+    "id": "org.crosswire.sword.cordova.SWORD",
+    "platforms": [
+      "android",
+      "amazon-fireos"
+    ]
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://crosswire.org/svn/sword"
+  },
+  "keywords": [
+    "cordova",
+    "sword",
+    "Bible",
+    "ecosystem:cordova",
+    "cordova-android",
+    "cordova-amazon-fireos"
+  ],
+  "author": "CrossWire Bible Society",
+  "license": "GNU 2.0"
+}

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/plugin.xml
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/plugin.xml	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/plugin.xml	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:rim="http://www.blackberry.com/ns/widgets"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    id="org.crosswire.sword.cordova.SWORD"
+    version="0.0.1">
+    <name>SWORD</name>
+    <description>The SWORD Project Plugin</description>
+    <license>GNU 2.0</license>
+    <keywords>cordova,sword,Bible</keywords>
+    <repo>https://crosswire.org/svn/sword</repo>
+    <issue>http://crosswire.org/tracker</issue>
+
+    <js-module src="www/SWORD.js" name="SWORD">
+        <clobbers target="SWORD" />
+    </js-module>
+
+    <!-- firefoxos
+    <platform name="firefoxos">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Device">
+                <param name="firefoxos-package" value="Device" />
+            </feature>
+        </config-file>
+
+        <js-module src="src/firefoxos/DeviceProxy.js" name="DeviceProxy">
+            <runs />
+        </js-module>
+    </platform>
+ -->
+    <!-- tizen
+    <platform name="tizen">
+        <js-module src="src/tizen/DeviceProxy.js" name="DeviceProxy">
+            <runs />
+        </js-module>
+    </platform>
+ -->
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="/*">
+            <feature name="SWORD" >
+                <param name="android-package" value="org.crosswire.sword.cordova.SWORD"/>
+            </feature>
+        </config-file>
+	<config-file target="AndroidManifest.xml" parent="/manifest">
+	    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+	</config-file>
+
+        <source-file src="src/android/SWORD.java" target-dir="src/org/crosswire/sword/cordova" />
+        <source-file src="src/android/SWMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/AndroidMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/SWModule.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/InstallMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="libs/android/armeabi/libsword.so" target-dir="libs/armeabi" />
+        <source-file src="libs/android/arm64-v8a/libsword.so" target-dir="libs/arm64-v8a" />
+        <source-file src="libs/android/x86/libsword.so" target-dir="libs/x86" />
+        <source-file src="libs/android/mips64/libsword.so" target-dir="libs/mips64" />
+        <source-file src="libs/android/mips/libsword.so" target-dir="libs/mips" />
+        <source-file src="libs/android/armeabi-v7a/libsword.so" target-dir="libs/armeabi-v7a" />
+        <source-file src="libs/android/x86_64/libsword.so" target-dir="libs/x86_64" />
+    </platform>
+
+    <!-- amazon-fireos -->
+    <platform name="amazon-fireos">
+        <config-file target="res/xml/config.xml" parent="/*">
+            <feature name="SWORD" >
+                <param name="android-package" value="org.crosswire.sword.cordova"/>
+            </feature>
+        </config-file>
+
+        <source-file src="src/android/SWORD.java" target-dir="src/org/crosswire/sword/cordova" />
+        <source-file src="src/android/SWMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/AndroidMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/SWModule.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="src/android/InstallMgr.java" target-dir="src/org/crosswire/android/sword" />
+        <source-file src="libs/android/armeabi/libsword.so" target-dir="libs/armeabi" />
+        <source-file src="libs/android/arm64-v8a/libsword.so" target-dir="libs/arm64-v8a" />
+        <source-file src="libs/android/x86/libsword.so" target-dir="libs/x86" />
+        <source-file src="libs/android/mips64/libsword.so" target-dir="libs/mips64" />
+        <source-file src="libs/android/mips/libsword.so" target-dir="libs/mips" />
+        <source-file src="libs/android/armeabi-v7a/libsword.so" target-dir="libs/armeabi-v7a" />
+        <source-file src="libs/android/x86_64/libsword.so" target-dir="libs/x86_64" />
+    </platform>
+    
+    <!-- ubuntu
+    <platform name="ubuntu">
+        <header-file src="src/ubuntu/device.h" />
+        <source-file src="src/ubuntu/device.cpp" />
+        <js-module src="src/ubuntu/device.js" name="DeviceProxy">
+            <merges target="device" />
+        </js-module>
+    </platform>
+ -->
+    <!-- ios
+    <platform name="ios">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Device">
+                <param name="ios-package" value="CDVDevice"/>
+            </feature>
+        </config-file>
+
+        <header-file src="src/ios/CDVDevice.h" />
+        <source-file src="src/ios/CDVDevice.m" />
+    </platform>
+ -->
+    <!-- blackberry10
+    <platform name="blackberry10">
+        <source-file src="src/blackberry10/index.js" target-dir="Device" />
+        <config-file target="www/config.xml" parent="/widget">
+            <feature name="Device" value="Device"/>
+        </config-file>
+        <config-file target="www/config.xml" parent="/widget/rim:permissions">
+            <rim:permit>read_device_identifying_information</rim:permit>
+        </config-file>
+    </platform>
+ -->
+    <!-- wp7
+    <platform name="wp7">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Device">
+                <param name="wp-package" value="Device"/>
+            </feature>
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
+            <Capability Name="ID_CAP_IDENTITY_DEVICE" />
+        </config-file>
+
+        <source-file src="src/wp/Device.cs" />
+    </platform>
+ -->
+    <!-- wp8
+    <platform name="wp8">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Device">
+                <param name="wp-package" value="Device"/>
+            </feature>
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
+            <Capability Name="ID_CAP_IDENTITY_DEVICE" />
+        </config-file>
+
+        <source-file src="src/wp/Device.cs" />
+    </platform>
+ -->
+    <!-- windows8
+    <platform name="windows8">
+        <js-module src="src/windows8/DeviceProxy.js" name="DeviceProxy">
+            <merges target="" />
+        </js-module>
+    </platform>
+ -->
+</plugin>

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/android/SWORD.java
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/android/SWORD.java	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/android/SWORD.java	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,655 @@
+/*
+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.crosswire.sword.cordova;
+
+import java.util.TimeZone;
+import java.util.Vector;
+import java.util.Map;
+import java.util.HashMap;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.CordovaInterface;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.crosswire.android.sword.SWMgr;
+import org.crosswire.android.sword.AndroidMgr;
+import org.crosswire.android.sword.SWModule;
+import org.crosswire.android.sword.InstallMgr;
+
+import android.provider.Settings;
+import android.util.Log;
+import android.content.Intent;
+import android.app.Activity;
+
+public class SWORD extends CordovaPlugin {
+	public static final String TAG = "SWORD";
+	public static SWMgr mgr = null;
+	public static InstallMgr installMgr = null;
+	private CallbackContext installReporterContext = null;
+	private CallbackContext searchReporterContext = null;
+	private CallbackContext renderChapterContext = null;
+	private CallbackContext sendContext = null;
+
+	/**
+	* Constructor.
+	*/
+	public SWORD() {
+	}
+
+	/**
+	* Sets the context of the Command. This can then be used to do things like
+	* get file paths associated with the Activity.
+	*
+	* @param cordova The context of the main Activity.
+	* @param webView The CordovaWebView Cordova is running in.
+	*/
+	public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+		super.initialize(cordova, webView);
+		mgr = new AndroidMgr(cordova.getActivity().getApplication());
+		installMgr = new InstallMgr();
+		installReporterContext = null;
+		searchReporterContext = null;
+		renderChapterContext = null;
+	}
+
+	/**
+	* Executes the request and returns PluginResult.
+	*
+	* @param action            The action to execute.
+	* @param args              JSONArry of arguments for the plugin.
+	* @param callbackContext   The callback id used when calling back into JavaScript.
+	* @return                  True if the action was valid, false if not.
+	*/
+	public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
+		if (action.equals("init")) {
+			JSONObject r = new JSONObject();
+			r.put("version", mgr.version());
+			callbackContext.success(r);
+		}
+		else if (action.equals("echo")) {
+			echo(callbackContext, args.getString(0));
+		}
+		else if (action.equals("InstallMgr.setUserDisclaimerConfirmed")) {
+			installMgr.setUserDisclaimerConfirmed();
+			callbackContext.success();
+		}
+		else if (action.equals("InstallMgr.syncConfig")) {
+			cordova.getThreadPool().execute(new Runnable() {
+				@Override
+				public void run() {
+					installMgr.syncConfig();
+					installMgr.reInit();
+					callbackContext.success();
+				}
+			});
+		}
+		else if (action.equals("InstallMgr.getRemoteSources")) {
+			JSONArray r = new JSONArray();
+			String sources[] = installMgr.getRemoteSources();
+			for (String s : sources) {
+				r.put(s);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("InstallMgr.refreshRemoteSource")) {
+			final String repo = args.getString(0);
+			cordova.getThreadPool().execute(new Runnable() {
+				@Override
+				public void run() {
+					installMgr.refreshRemoteSource(repo);
+					callbackContext.success();
+				}
+			});
+		}
+		else if (action.equals("InstallMgr.getRemoteModInfoList")) {
+			JSONArray r = new JSONArray();
+			for (SWMgr.ModInfo mi : installMgr.getRemoteModInfoList(args.getString(0))) {
+				JSONObject m = new JSONObject();
+				m.put("name", mi.name);
+				m.put("description", mi.description);
+				m.put("category", mi.category);
+				m.put("language", mi.language);
+				m.put("version", mi.version);
+				m.put("delta", mi.delta);
+				r.put(m);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("InstallMgr.remoteInstallModule")) {
+			this.installReporterContext = callbackContext;
+			final String repo = args.getString(0);
+			final String modName = args.getString(1);
+			cordova.getThreadPool().execute(new Runnable() {
+			    @Override
+			    public void run() {
+
+				installMgr.remoteInstallModule(repo, modName, new InstallMgr.InstallProgressReporter() {
+					public void update(long totalBytes, long completedBytes) {
+	/*
+	// callback({ status : preStatus|update|complete, totalBytes : n, completedBytes : n, message : displayable });
+	*/
+						try {
+
+							JSONObject m = new JSONObject();
+							m.put("status", "update");
+							m.put("totalBytes", totalBytes);
+							m.put("completedBytes", completedBytes);
+							if (installReporterContext != null) {
+								PluginResult result = new PluginResult(PluginResult.Status.OK, m);
+								result.setKeepCallback(true);
+								installReporterContext.sendPluginResult(result);
+							}
+						}
+						catch (Exception e) { e.printStackTrace(); }
+					}
+					public void preStatus(long totalBytes, long completedBytes, String message) {
+						try {
+							JSONObject m = new JSONObject();
+							m.put("status", ("Complete".equals(message)) ? "complete" : "preStatus");
+							m.put("totalBytes", totalBytes);
+							m.put("completedBytes", completedBytes);
+							m.put("message", message);
+							if (installReporterContext != null) {
+								PluginResult result = new PluginResult(PluginResult.Status.OK, m);
+								result.setKeepCallback(!"Complete".equals(message));
+								installReporterContext.sendPluginResult(result);
+							}
+							if ("Complete".equals(message)) {
+								// let's be sure we see our new module
+								mgr.reInit();
+								// and clear out context
+								installReporterContext = null;
+							}
+						}
+						catch (Exception e) { e.printStackTrace(); }
+					}
+				});
+
+			    }
+			});
+
+			PluginResult result = new PluginResult(PluginResult.Status.OK);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else if (action.equals("InstallMgr.uninstallModule")) {
+			installMgr.uninstallModule(args.getString(0));
+			callbackContext.success();
+		}
+		else if (action.equals("SWMgr.getExtraConfigSections")) {
+			JSONArray r = new JSONArray();
+			for (String s : mgr.getExtraConfigSections()) {
+				r.put(s);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWMgr.getExtraConfigKeys")) {
+			JSONArray r = new JSONArray();
+			for (String s : mgr.getExtraConfigKeys(args.getString(0))) {
+				r.put(s);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWMgr.getExtraConfigValue")) {
+			callbackContext.success(mgr.getExtraConfigValue(args.getString(0), args.getString(1)));
+		}
+		else if (action.equals("SWMgr.setExtraConfigValue")) {
+			mgr.setExtraConfigValue(args.getString(0), args.getString(1), args.getString(2));
+			callbackContext.success();
+		}
+		else if (action.equals("SWMgr.addExtraConfig")) {
+			JSONArray r = new JSONArray();
+			for (String s : mgr.addExtraConfig(args.getString(0))) {
+				r.put(s);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWMgr.getModInfoList")) {
+			JSONArray r = new JSONArray();
+			for (SWMgr.ModInfo mi : mgr.getModInfoList()) {
+				JSONObject m = new JSONObject();
+				m.put("name", mi.name);
+				m.put("description", mi.description);
+				m.put("category", mi.category);
+				m.put("language", mi.language);
+				m.put("version", mi.version);
+				m.put("delta", mi.delta);
+				r.put(m);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWMgr.getModuleByName")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			// didn't find module is not an error
+			if (mod == null) { callbackContext.success(); return true; }
+
+			JSONObject m = new JSONObject();
+			m.put("name", mod.getName());
+			m.put("description", mod.getDescription());
+			m.put("category", mod.getCategory());
+			m.put("direction", mod.getConfigEntry("Direction"));
+			m.put("language", mod.getConfigEntry("Lang"));
+			m.put("font", mod.getConfigEntry("Font"));
+			m.put("shortCopyright", mod.getConfigEntry("ShortCopyright"));
+			m.put("shortPromo", mod.getConfigEntry("ShortPromo"));
+			callbackContext.success(m);
+		}
+		else if (action.equals("SWModule.setKeyText")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			mod.setKeyText(args.getString(1));
+			callbackContext.success();
+		}
+		else if (action.equals("SWModule.getKeyText")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success(mod.getKeyText());
+		}
+		else if (action.equals("SWModule.search")) {
+			this.searchReporterContext = callbackContext;
+			final SWModule mod = mgr.getModuleByName(args.getString(0));
+			final String expression = args.getString(1);
+			final int searchType = args.getInt(2);
+			final long flags = args.getLong(3);
+			final String scope = JSONObject.NULL.equals(args.getString(4)) || "null".equals(args.getString(4)) ? null : args.getString(4);
+			cordova.getThreadPool().execute(new Runnable() {
+			    @Override
+			    public void run() {
+
+				SWModule.SearchHit[] results = mod.search(expression, searchType, flags, scope, new SWModule.SearchProgressReporter() {
+					public void progressReport(int percent) {
+						try {
+							JSONObject m = new JSONObject();
+							m.put("status", "update");
+							m.put("percent", percent);
+							if (searchReporterContext != null) {
+								PluginResult result = new PluginResult(PluginResult.Status.OK, m);
+								result.setKeepCallback(true);
+								searchReporterContext.sendPluginResult(result);
+							}
+						}
+						catch (Exception e) { e.printStackTrace(); }
+					}
+				});
+				try {
+					JSONObject m = new JSONObject();
+					m.put("status", "complete");
+					m.put("percent", 100);
+					JSONArray r = new JSONArray();
+					for (SWModule.SearchHit s : results) {
+						JSONObject re = new JSONObject();
+						re.put("key", s.key);
+						re.put("score", s.score);
+						r.put(re);
+					}
+					m.put("results", r);
+					if (searchReporterContext != null) {
+						PluginResult result = new PluginResult(PluginResult.Status.OK, m);
+						result.setKeepCallback(false);
+						searchReporterContext.sendPluginResult(result);
+					}
+				}
+				catch (Exception e) { e.printStackTrace(); }
+				searchReporterContext = null;
+			    }
+			});
+
+			PluginResult result = new PluginResult(PluginResult.Status.OK);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else if (action.equals("SWModule.getRenderChapter")) {
+			this.renderChapterContext = callbackContext;
+
+			final SWModule masterMod = mgr.getModuleByName(args.getString(0));
+			final SWModule mod = mgr.getModuleByName(args.getString(1));
+			if (masterMod == null) { callbackContext.error("couldn't find master module: " + args.getString(0)); return true; }
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(1)); return true; }
+
+			cordova.getThreadPool().execute(new Runnable() {
+			    @Override
+			    public void run() {
+
+				JSONArray r = new JSONArray();
+				try {
+					r = getRenderChapter(masterMod, mod);
+				} catch (JSONException e) { e.printStackTrace(); }
+				PluginResult result = new PluginResult(PluginResult.Status.OK, r);
+				result.setKeepCallback(false);
+				if (renderChapterContext != null) {
+					renderChapterContext.sendPluginResult(result);
+					renderChapterContext = null;
+				}
+			    }
+			});
+
+			PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else if (action.equals("SWMgr.registerBibleSyncListener")) {
+			final CallbackContext bibleSyncListener = callbackContext;
+
+			cordova.getThreadPool().execute(new Runnable() {
+			    @Override
+			    public void run() {
+				mgr.registerBibleSyncListener(new SWMgr.BibleSyncListener() {
+					public void messageReceived(String message) {
+						PluginResult result = new PluginResult(PluginResult.Status.OK, message);
+						result.setKeepCallback(true);
+						bibleSyncListener.sendPluginResult(result);
+					}
+				});
+			    }
+			});
+
+			PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else if (action.equals("SWMgr.sendBibleSyncMessage")) {
+			String osisRef = args.getString(0);
+			mgr.sendBibleSyncMessage(osisRef);
+			callbackContext.success();
+		}
+		else if (action.equals("SWModule.getRenderText")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success(mod.getRenderText());
+		}
+		else if (action.equals("SWModule.sendText")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			this.sendContext = callbackContext;
+			sendVerse(mod, new String[] { mod.getKeyText() }, cordova, this);
+			PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else if (action.equals("SWModule.getRenderHeader")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success(mod.getRenderHeader());
+		}
+		else if (action.equals("SWModule.getKeyChildren")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			JSONArray r = new JSONArray();
+			for (String k : mod.getKeyChildren()) {
+				r.put(k);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWModule.getConfigEntry")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success(mod.getConfigEntry(args.getString(1)));
+		}
+		else if (action.equals("SWModule.getEntryAttribute")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			JSONArray r = new JSONArray();
+			for (String k : mod.getEntryAttribute(args.getString(1), args.getString(2), args.getString(3), args.getBoolean(4))) {
+				r.put(k);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("SWModule.popError")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success((int)mod.error());
+		}
+		else if (action.equals("SWModule.next")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			mod.next();
+			callbackContext.success();
+		}
+		else if (action.equals("SWModule.previous")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			mod.previous();
+			callbackContext.success();
+		}
+		else if (action.equals("SWModule.begin")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			mod.begin();
+			callbackContext.success();
+		}
+		else if (action.equals("SWModule.getVerseKey")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			callbackContext.success(getVerseKey(mod.getKeyChildren()));
+		}
+		else if (action.equals("SWModule.getBookNames")) {
+			SWModule mod = mgr.getModuleByName(args.getString(0));
+			if (mod == null) { callbackContext.error("couldn't find module: " + args.getString(0)); return true; }
+			JSONArray r = new JSONArray();
+			for (String b : getBookNames(mod)) {
+				r.put(b);
+			}
+			callbackContext.success(r);
+		}
+		else if (action.equals("HTTPUtils.makeRequest")) {
+			final CallbackContext makeRequestContext = callbackContext;
+
+			final String url      = args.getString(0);
+			final String postData = args.getString(1);
+			final int method      = args.getInt(2);
+Log.d(TAG, "makeRequest(url: " + url + ", postData: " + postData + ", method: " + method);
+
+			cordova.getThreadPool().execute(new Runnable() {
+				@Override
+				public void run() {
+					String response = makeRequest(url, postData, method, null);
+					PluginResult result = new PluginResult(PluginResult.Status.OK, response);
+					result.setKeepCallback(false);
+					makeRequestContext.sendPluginResult(result);
+				}
+			});
+
+			PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
+			result.setKeepCallback(true);
+			callbackContext.sendPluginResult(result);
+		}
+		else return false;
+
+		return true;
+	}
+
+	JSONObject getVerseKey(String keyChildren[]) throws JSONException {
+		JSONObject retVal = new JSONObject();
+		if (keyChildren != null && keyChildren.length > 9) {
+			retVal.put("testament",  Integer.parseInt(keyChildren[SWModule.VERSEKEY_TESTAMENT]));
+			retVal.put("book",       Integer.parseInt(keyChildren[SWModule.VERSEKEY_BOOK]));
+			retVal.put("chapter",    Integer.parseInt(keyChildren[SWModule.VERSEKEY_CHAPTER]));
+			retVal.put("verse",      Integer.parseInt(keyChildren[SWModule.VERSEKEY_VERSE]));
+			retVal.put("chapterMax", Integer.parseInt(keyChildren[SWModule.VERSEKEY_CHAPTERMAX]));
+			retVal.put("verseMax",   Integer.parseInt(keyChildren[SWModule.VERSEKEY_VERSEMAX]));
+			retVal.put("bookName",   keyChildren[SWModule.VERSEKEY_BOOKNAME]);
+			retVal.put("osisRef",    keyChildren[SWModule.VERSEKEY_OSISREF]);
+			retVal.put("shortText",  keyChildren[SWModule.VERSEKEY_SHORTTEXT]);
+			retVal.put("bookAbbrev", keyChildren[SWModule.VERSEKEY_BOOKABBREV]);
+		}
+		return retVal;
+	}
+
+	public JSONArray getRenderChapter(SWModule masterMod, SWModule mod) throws JSONException {
+		JSONArray r = new JSONArray();
+
+		// save our current keys so we can set our mods back when we're done
+		String saveMasterKey = masterMod.getKeyText();
+		String saveKey = mod.getKeyText();
+
+		String currentKey[]   = masterMod.getKeyChildren();
+
+		masterMod.setKeyText(currentKey[SWModule.VERSEKEY_BOOKABBREV]+"."+currentKey[SWModule.VERSEKEY_CHAPTER]+".1");
+
+		String [] verseKey = masterMod.getKeyChildren();
+		while (
+				   masterMod.error() == 0
+				&& currentKey[SWModule.VERSEKEY_BOOK].equals(verseKey[SWModule.VERSEKEY_BOOK])
+				&& currentKey[SWModule.VERSEKEY_CHAPTER].equals(verseKey[SWModule.VERSEKEY_CHAPTER])) {
+
+			mod.setKeyText(verseKey[SWModule.VERSEKEY_OSISREF]);
+			char error = mod.error();
+			JSONObject v = new JSONObject();
+			if (((int)error) == 0) {
+				v.put("verse", getVerseKey(mod.getKeyChildren()));
+				String preVerse = "";
+				for (String h : mod.getEntryAttribute("Heading", "Preverse", "", true)) {
+					preVerse += h;
+				}
+				v.put("preVerse", preVerse);
+				v.put("text", mod.getRenderText());
+			}
+			else {
+/* null removes entry
+				v.put("verse", null);
+				v.put("preVerse", null);
+				v.put("text", null);
+*/
+			}
+			r.put(v);
+			masterMod.next();
+			verseKey = masterMod.getKeyChildren();
+		}
+
+		masterMod.setKeyText(saveMasterKey);
+		mod.setKeyText(saveKey);
+
+		return r;
+	}
+
+
+	public Vector<String> getBookNames(SWModule mod) {
+		Vector<String> books = new Vector<String>();
+		for (mod.begin(); mod.error() == 0; mod.setKeyText("+book")) {
+			books.add(mod.getKeyChildren()[9]);
+		}
+		return books;
+	}
+
+	//--------------------------------------------------------------------------
+	// LOCAL METHODS
+	//--------------------------------------------------------------------------
+
+	public void echo(CallbackContext callbackContext, String message) {
+		if (message != null && message.length() > 0) {
+			callbackContext.success(message);
+		}
+		else {
+			callbackContext.error("expected 1 arg");
+		}
+	}
+
+	public static final int METHOD_GET  = 0;
+	public static final int METHOD_POST = 1;
+	public static final String METHODS_TEXT[] = { "GET", "POST" };
+
+	public static String makeRequest(String url, String postData, int method, Map<String, String> headers) {
+		HttpURLConnection connection = null;
+
+		Map<String, String> defaultHeaders = new HashMap<String, String>();
+		defaultHeaders.put("Accept", "*/*");
+//		defaultHeaders.put("Content-Type", "application/xml");
+	 	defaultHeaders.put("Content-Type", "application/x-www-form-urlencoded");
+		if (method != METHOD_GET && postData != null) defaultHeaders.put("Content-Length", Integer.toString(postData.length()));
+
+		try {
+			if (headers != null) defaultHeaders.putAll(headers);
+
+			if (method == METHOD_GET && postData != null && postData.length() > 0) {
+				// some sanity checks for appending GET params to URL
+				if (url.indexOf("?") < 0) if (!postData.startsWith("?")) url += "?";
+				else if (!url.endsWith("&") && !postData.startsWith("&")) url += "&";
+
+				url += postData;
+			}
+
+			connection = (HttpURLConnection) new URL(url).openConnection();
+			connection.setRequestMethod(METHODS_TEXT[method]);
+			for (String k : defaultHeaders.keySet()) {
+				connection.setRequestProperty(k, defaultHeaders.get(k));
+			}
+			if (method == METHOD_POST) {
+				connection.setDoOutput(true);
+				if (postData != null) {
+					DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
+					dos.writeBytes(postData);
+					dos.flush();
+					dos.close();
+				}
+			}
+			int responseCode = connection.getResponseCode();
+			BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+			StringBuilder response = new StringBuilder();
+			String line;
+			while ((line = br.readLine()) != null) {
+				response.append(line);
+			}
+			/* do something special if success code?
+			if (responseCode >= 200 && responseCode < 300) {
+			}
+			else throw new Exception("HTTP Response: " + responseCode);
+			*/
+			return response.toString();
+		}
+		catch (Exception e) { e.printStackTrace(); }
+		return null;
+	}
+	public static void sendVerse(final SWModule mod, final String verse[], final CordovaInterface cordova, final CordovaPlugin plugin) {
+		cordova.getThreadPool().execute(new Runnable() {
+			public void run() {
+				String subject = mod.getKeyChildren()[SWModule.VERSEKEY_SHORTTEXT] + " (" + mod.getName() + ")";
+				String message = mod.getStripText() + " --" +subject;
+				final Intent sendIntent = new Intent(Intent.ACTION_SEND);
+				sendIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+
+				sendIntent.setType("text/plain");
+
+				sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+				sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
+
+				cordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), 1);
+			}
+		});
+	}
+
+	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+		switch (requestCode) {
+		case 1: 
+			sendContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, resultCode == Activity.RESULT_OK));
+		}
+		super.onActivityResult(requestCode, resultCode, intent);
+	}
+
+}

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10/index.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10/index.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/blackberry10/index.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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 getModelName () {
+    var modelName = window.qnx.webplatform.device.modelName;
+    //Pre 10.2 (meaning Z10 or Q10)
+    if (typeof modelName === "undefined") {
+        if (window.screen.height === 720 && window.screen.width === 720) {
+            if ( window.matchMedia("(-blackberry-display-technology: -blackberry-display-oled)").matches) {
+                modelName = "Q10";
+            } else {
+                modelName = "Q5";
+            }
+        } else if ((window.screen.height === 1280 && window.screen.width === 768) ||
+                   (window.screen.height === 768 && window.screen.width === 1280)) {
+            modelName = "Z10";
+        } else {
+            modelName = window.qnx.webplatform.deviceName;
+        }
+    }
+
+    return modelName;
+}
+
+function getUUID () {
+    var uuid = "";
+    try {
+        //Must surround by try catch because this will throw if the app is missing permissions
+        uuid = window.qnx.webplatform.device.devicePin;
+    } catch (e) {
+        //DO Nothing
+    }
+    return uuid;
+}
+
+module.exports = {
+    getDeviceInfo: function (success, fail, args, env) {
+        var result = new PluginResult(args, env),
+            modelName = getModelName(),
+            uuid = getUUID(),
+            info = {
+                platform: "blackberry10",
+                version: window.qnx.webplatform.device.scmBundle,
+                model: modelName,
+                uuid: uuid,
+                cordova: "dev"
+            };
+
+        result.ok(info);
+    }
+};

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos/DeviceProxy.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos/DeviceProxy.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/firefoxos/DeviceProxy.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 firefoxos = require('cordova/platform');
+var cordova = require('cordova');
+
+module.exports = {
+    getDeviceInfo: function(success, error) {
+        setTimeout(function () {
+            success({
+                cordova: firefoxos.cordovaVersion,
+                platform: 'firefoxos',
+                model: null,
+                version: null,
+                uuid: null
+            });
+        }, 0);
+    }
+};
+
+require("cordova/firefoxos/commandProxy").add("Device", module.exports);

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.h
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.h	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.h	2017-11-01 10:37:19 UTC (rev 3509)
@@ -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 <UIKit/UIKit.h>
+#import <Cordova/CDVPlugin.h>
+
+ at interface CDVDevice : CDVPlugin
+{}
+
++ (NSString*)cordovaVersion;
+
+- (void)getDeviceInfo:(CDVInvokedUrlCommand*)command;
+
+ at end

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.m
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.m	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ios/CDVDevice.m	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,90 @@
+/*
+ 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.
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#import <Cordova/CDV.h>
+#import "CDVDevice.h"
+
+ at implementation UIDevice (ModelVersion)
+
+- (NSString*)modelVersion
+{
+    size_t size;
+
+    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+    char* machine = malloc(size);
+    sysctlbyname("hw.machine", machine, &size, NULL, 0);
+    NSString* platform = [NSString stringWithUTF8String:machine];
+    free(machine);
+
+    return platform;
+}
+
+ at end
+
+ at interface CDVDevice () {}
+ at end
+
+ at implementation CDVDevice
+
+- (void)getDeviceInfo:(CDVInvokedUrlCommand*)command
+{
+    NSDictionary* deviceProperties = [self deviceProperties];
+    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:deviceProperties];
+
+    /* Settings.plist
+     * Read the optional Settings.plist file and push these user-defined settings down into the web application.
+     * This can be useful for supplying build-time configuration variables down to the app to change its behavior,
+     * such as specifying Full / Lite version, or localization (English vs German, for instance).
+     */
+    // TODO: turn this into an iOS only plugin
+    NSDictionary* temp = [CDVViewController getBundlePlist:@"Settings"];
+
+    if ([temp respondsToSelector:@selector(JSONString)]) {
+        NSLog(@"Deprecation warning: window.Setting will be removed Aug 2013. Refer to https://issues.apache.org/jira/browse/CB-2433");
+        NSString* js = [NSString stringWithFormat:@"window.Settings = %@;", [temp JSONString]];
+        [self.commandDelegate evalJs:js];
+    }
+
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (NSDictionary*)deviceProperties
+{
+    UIDevice* device = [UIDevice currentDevice];
+    NSMutableDictionary* devProps = [NSMutableDictionary dictionaryWithCapacity:4];
+
+    [devProps setObject:[device modelVersion] forKey:@"model"];
+    [devProps setObject:@"iOS" forKey:@"platform"];
+    [devProps setObject:[device systemVersion] forKey:@"version"];
+    [devProps setObject:[device uniqueAppInstanceIdentifier] forKey:@"uuid"];
+    [devProps setObject:[[self class] cordovaVersion] forKey:@"cordova"];
+
+    NSDictionary* devReturn = [NSDictionary dictionaryWithDictionary:devProps];
+    return devReturn;
+}
+
++ (NSString*)cordovaVersion
+{
+    return CDV_VERSION;
+}
+
+ at end

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/tizen/DeviceProxy.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/tizen/DeviceProxy.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/tizen/DeviceProxy.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 tizen = require('cordova/platform');
+var cordova = require('cordova');
+
+module.exports = {
+    getDeviceInfo: function(success, error) {
+        setTimeout(function () {
+            success({
+                cordova: tizen.cordovaVersion,
+                platform: 'tizen',
+                model: null,
+                version: null,
+                uuid: null
+            });
+        }, 0);
+    }
+};
+
+require("cordova/tizen/commandProxy").add("Device", module.exports);

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.cpp
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.cpp	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.cpp	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,64 @@
+/*
+ *  Copyright 2011 Wolfgang Koller - http://www.gofg.at/
+ *
+ *  Licensed 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.
+ */
+
+#include <QDeviceInfo>
+#include <QtSystemInfo>
+
+#include"device.h"
+
+#define CORDOVA "3.0.0"
+
+Device::Device(Cordova *cordova) : CPlugin(cordova) {
+}
+
+static QString getOSName() {
+#ifdef Q_OS_SYMBIAN
+    QString platform = "Symbian";
+#endif
+#ifdef Q_OS_WIN
+    QString platform = "Windows";
+#endif
+#ifdef Q_OS_WINCE
+    QString platform = "Windows CE";
+#endif
+#ifdef Q_OS_LINUX
+    QString platform = "Linux";
+#endif
+    return platform;
+}
+
+void Device::getInfo(int scId, int ecId) {
+    Q_UNUSED(ecId)
+
+    QDeviceInfo systemDeviceInfo;
+    QDeviceInfo systemInfo;
+
+    QString platform = getOSName();
+
+    QString uuid = systemDeviceInfo.uniqueDeviceID();
+    if (uuid.isEmpty()) {
+        QString deviceDescription = systemInfo.imei(0) + ";" + systemInfo.manufacturer() + ";" + systemInfo.model() + ";" + systemInfo.productName() + ";" + platform;
+        QString user = qgetenv("USER");
+        if (user.isEmpty()) {
+            user = qgetenv("USERNAME");
+            if (user.isEmpty())
+                user = QDir::homePath();
+        }
+        uuid = QString(QCryptographicHash::hash((deviceDescription + ";" + user).toUtf8(), QCryptographicHash::Md5).toHex());
+    }
+
+    this->cb(scId, systemDeviceInfo.model(), CORDOVA, platform, uuid, systemInfo.version(QDeviceInfo::Os));
+}

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.h
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.h	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.h	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,47 @@
+/*
+ *  Copyright 2011 Wolfgang Koller - http://www.gofg.at/
+ *
+ *  Licensed 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.
+ */
+
+#ifndef DEVICE_H_FDSAFAS
+#define DEVICE_H_FDSAFAS
+
+#include <QtCore>
+
+#include <cplugin.h>
+
+class Device: public CPlugin {
+    Q_OBJECT
+public:
+    explicit Device(Cordova *cordova);
+
+    virtual const QString fullName() override {
+        return Device::fullID();
+    }
+
+    virtual const QString shortName() override {
+        return "Device";
+    }
+
+    static const QString fullID() {
+        return "com.cordova.Device";
+    }
+
+signals:
+
+public slots:
+    void getInfo(int scId, int ecId);
+};
+
+#endif

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/ubuntu/device.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 cordova = require('cordova');
+var exec = require('cordova/exec');
+
+module.exports = {
+    getInfo:function(win,fail,args) {
+        Cordova.exec(function (model, cordova, platform, uuid, version) {
+            win({name: name, model: model, cordova: cordova,
+                 platform: platform, uuid: uuid, version: version});
+        }, null, "com.cordova.Device", "getInfo", []);
+    }
+};
+
+require("cordova/exec/proxy").add("Device", module.exports);

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/windows8/DeviceProxy.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/windows8/DeviceProxy.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/windows8/DeviceProxy.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 cordova = require('cordova');
+var utils = require('cordova/utils');
+
+module.exports = {
+
+    getDeviceInfo:function(win,fail,args) {
+
+        // deviceId aka uuid, stored in Windows.Storage.ApplicationData.current.localSettings.values.deviceId
+        var deviceId;
+
+        var localSettings = Windows.Storage.ApplicationData.current.localSettings;
+
+        if (localSettings.values.deviceId) {
+            deviceId = localSettings.values.deviceId;
+        }
+        else {
+            deviceId = localSettings.values.deviceId = utils.createUUID();
+        }
+
+        setTimeout(function () {
+            win({ platform: "windows8", version: "8", uuid: deviceId, cordova: '0.0.0', model: window.clientInformation.platform });
+        }, 0);
+    }
+
+};
+
+require("cordova/windows8/commandProxy").add("Device", module.exports);
+

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/wp/Device.cs
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/wp/Device.cs	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/src/wp/Device.cs	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,135 @@
+/*  
+	Licensed 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.
+*/
+
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using Microsoft.Phone.Info;
+using System.IO.IsolatedStorage;
+using System.Windows.Resources;
+using System.IO;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+    public class Device : BaseCommand
+    {
+        public void getDeviceInfo(string notused)
+        {
+
+            string res = String.Format("\"name\":\"{0}\",\"cordova\":\"{1}\",\"platform\":\"{2}\",\"uuid\":\"{3}\",\"version\":\"{4}\",\"model\":\"{5}\"",
+                                        this.name,
+                                        this.cordova,
+                                        this.platform,
+                                        this.uuid,
+                                        this.version,
+                                        this.model);
+
+
+
+            res = "{" + res + "}";
+            //Debug.WriteLine("Result::" + res);
+            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res));
+        }
+
+        public string model
+        {
+            get
+            {
+                return DeviceStatus.DeviceName;
+                //return String.Format("{0},{1},{2}", DeviceStatus.DeviceManufacturer, DeviceStatus.DeviceHardwareVersion, DeviceStatus.DeviceFirmwareVersion); 
+            }
+        }
+
+        public string name
+        {
+            get
+            {
+                return DeviceStatus.DeviceName;
+                
+            }
+        }
+
+        public string cordova
+        {
+            get
+            {
+                // TODO: should be able to dynamically read the Cordova version from somewhere...
+                return "3.0.0";
+            }
+        }
+
+        public string platform
+        {
+            get
+            {
+                return Environment.OSVersion.Platform.ToString();
+            }
+        }
+
+        public string uuid
+        {
+            get
+            {
+                string returnVal = "";
+                object id;
+                UserExtendedProperties.TryGetValue("ANID", out id);
+
+                if (id != null)
+                {
+                    returnVal = id.ToString().Substring(2, 32);
+                }
+                else
+                {
+                    returnVal = "???unknown???";
+
+                    using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
+                    {
+                        try
+                        {
+                            IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Open, FileAccess.Read, appStorage);
+
+                            using (StreamReader reader = new StreamReader(fileStream))
+                            {
+                                returnVal = reader.ReadLine();
+                            }
+                        }
+                        catch (Exception /*ex*/)
+                        {
+
+                        }
+                    }
+                }
+
+                return returnVal;
+            }
+        }
+
+        public string version
+        {
+            get
+            {
+                return Environment.OSVersion.Version.ToString();
+            }
+        }
+
+    }
+}

Added: trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/www/SWORD.js
===================================================================
--- trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/www/SWORD.js	                        (rev 0)
+++ trunk/bindings/cordova/org.crosswire.sword.cordova.SWORD/www/SWORD.js	2017-11-01 10:37:19 UTC (rev 3509)
@@ -0,0 +1,407 @@
+var	argscheck = require('cordova/argscheck'),
+	channel   = require('cordova/channel'),
+	utils     = require('cordova/utils'),
+	exec      = require('cordova/exec'),
+	cordova   = require('cordova');
+
+channel.createSticky('onSWORDReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onSWORDReady');
+
+
+function InstallMgr() {
+}
+
+InstallMgr.prototype.setUserDisclaimerConfirmed = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.setUserDisclaimerConfirmed", []
+	);
+	return retVal;
+}
+
+InstallMgr.prototype.syncConfig = function(callback, progressNotify) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.syncConfig", [progressNotify]
+	);
+	return retVal;
+}
+
+
+InstallMgr.prototype.getRemoteSources = function(callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.getRemoteSources", []
+	);
+	return retVal;
+}
+
+
+InstallMgr.prototype.refreshRemoteSource = function(sourceName, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.refreshRemoteSource", [sourceName]
+	);
+	return retVal;
+}
+
+InstallMgr.prototype.getRemoteModInfoList = function(sourceName, callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.getRemoteModInfoList", [sourceName]
+	);
+	return retVal;
+}
+
+// callback({ status : preStatus|update|complete, totalBytes : n, completedBytes : n, message : displayable });
+InstallMgr.prototype.remoteInstallModule = function(sourceName, modName, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.remoteInstallModule", [sourceName, modName]
+	);
+	return retVal;
+}
+
+InstallMgr.prototype.uninstallModule = function(modName, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "InstallMgr.uninstallModule", [modName]
+	);
+	return retVal;
+}
+
+function SWModule(modInfo) {
+	this.name           = modInfo.name;
+	this.description    = modInfo.description;
+	this.category       = modInfo.category;
+	this.direction      = modInfo.direction;
+	this.language       = modInfo.language;
+	this.font           = modInfo.font;
+	this.shortCopyright = modInfo.shortCopyright;
+	this.shortPromo     = modInfo.shortPromo;
+}
+
+SWModule.prototype.SEARCHTYPE_REGEX     =  1;
+SWModule.prototype.SEARCHTYPE_PHRASE    = -1;
+SWModule.prototype.SEARCHTYPE_MULTIWORD = -2;
+SWModule.prototype.SEARCHTYPE_ENTRYATTR = -3;
+SWModule.prototype.SEARCHTYPE_LUCENE    = -4;
+
+SWModule.prototype.SEARCHOPTION_ICASE   = 2;
+
+
+SWModule.prototype.setKeyText = function(keyText, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.setKeyText", [this.name, keyText]
+	);
+	return retVal;
+}
+
+SWModule.prototype.search = function(expression, searchType, flags, scope, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.search", [this.name, expression, searchType, flags, scope]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getKeyText = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getKeyText", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getRenderText = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getRenderText", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.shareVerse = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.sendText", [this.name]
+	);
+	return retVal;
+}
+
+/*
+ * masterMod - SWModule to use for traversing chapter; null if self
+ * 	useful for parallel display with alternate v11ns
+ *
+ * returns [ { verse : verseKey,  preVerse : 'text', text : 'text' }, ... }
+ */
+SWModule.prototype.getRenderChapter = function(masterMod, callback) {
+	var retVal = null;
+	if (!masterMod) masterMod = this;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getRenderChapter", [masterMod.name, this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getRenderHeader = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getRenderHeader", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getKeyChildren = function(callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getKeyChildren", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getVerseKey = function(callback) {
+	var retVal = {};
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getVerseKey", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getConfigEntry = function(key, callback) {
+	var retVal = '';
+	exec(callback?callback:function(m) { if (m) retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getConfigEntry", [this.name, key]
+	);
+	return retVal;
+}
+
+
+SWModule.prototype.popError = function(callback) {
+	var retVal = 0;
+	exec(callback?callback:function(m) { retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.popError", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getEntryAttribute = function(level1Key, level2Key, level3Key, isFiltered, callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getEntryAttribute", [this.name, level1Key, level2Key, level3Key, isFiltered]
+	);
+	return retVal;
+}
+
+SWModule.prototype.next = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.next", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.previous = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.previous", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.begin = function(callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.begin", [this.name]
+	);
+	return retVal;
+}
+
+SWModule.prototype.getBookNames = function(callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWModule.getBookNames", [this.name]
+	);
+	return retVal;
+}
+
+function SWMgr() {
+}
+
+
+SWMgr.prototype.getModInfoList = function(callback) {
+	var retVal = [];
+	exec(callback?callback:function(m) { if (m && m.length > 0) retVal = m; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.getModInfoList", []
+	);
+	return retVal;
+}
+
+SWMgr.prototype.getModuleByName = function(modName, callback) {
+	var mod = null;
+	exec(function(m) { if (m.name) mod = new SWModule(m); if (callback) callback(mod); },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.getModuleByName", [modName]
+	);
+	return mod;
+}
+
+SWMgr.prototype.getExtraConfigSections = function(callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.getExtraConfigSections", []
+	);
+	return retVal;
+}
+
+SWMgr.prototype.getExtraConfigKeys = function(section, callback) {
+	var retVal = [];
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.getExtraConfigKeys", [section]
+	);
+	return retVal;
+}
+
+SWMgr.prototype.getExtraConfigValue = function(section, key, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.getExtraConfigValue", [section, key]
+	);
+	return retVal;
+}
+
+SWMgr.prototype.setExtraConfigValue = function(section, key, value, callback) {
+	exec(callback?callback:function() {},
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.setExtraConfigValue", [section, key, value]
+	);
+}
+
+SWMgr.prototype.addExtraConfig = function(confBlob, callback) {
+	var retVal = null;
+	exec(callback?callback:function(r) { retVal = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.addExtraConfig", [confBlob]
+	);
+	return retVal;
+}
+
+SWMgr.prototype.registerBibleSyncListener = function(callback) {
+	exec(callback,
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.registerBibleSyncListener", []
+	);
+}
+
+SWMgr.prototype.sendBibleSyncMessage = function(osisRef, callback) {
+	exec(callback?callback:function() {},
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "SWMgr.sendBibleSyncMessage", [osisRef]
+	);
+}
+
+function HTTPUtils() {}
+
+HTTPUtils.prototype.METHOD_GET  =  0;
+HTTPUtils.prototype.METHOD_POST =  1;
+
+HTTPUtils.prototype.makeRequest = function(url, postData, callback, method) {
+	var result = null;
+	if (!method) method = this.METHOD_POST;
+	exec(callback?callback:function(r) { if (r && r.length > 0) result = r; },
+		function(err) { utils.alert('[ERROR] problem: ' + err); },
+		"SWORD", "HTTPUtils.makeRequest", [url, postData, method]
+	);
+	return result;
+}
+
+
+
+/*
+	public native String      getPrefixPath();
+	public native String      getConfigPath();
+	public native void        setGlobalOption(String option, String value);
+	public native String      getGlobalOption(String option);
+	public native String      getGlobalOptionTip(String option);
+	public native String      filterText(String filterName, String text);
+	public native String[]    getGlobalOptions();
+	public native String[]    getGlobalOptionValues(String option);
+	public native void        setCipherKey(String modName, String key);
+	public native void        setJavascript(boolean val);
+	public native String[]    getAvailableLocales();
+	public native void        setDefaultLocale(String name);
+*/
+
+
+/**
+ * This is the SWORD namespace and access to singleton SWMgr, InstallMgr, and HTTPUtils.
+ * @constructor
+ */
+function SWORD() {
+
+	var me = this;
+
+	this.available = false;
+	this.version = null;
+
+	this.installMgr = new InstallMgr();
+	this.mgr        = new SWMgr();
+	this.httpUtils  = new HTTPUtils();
+
+	channel.onCordovaReady.subscribe(function() {
+		me.init(function(info) {
+			me.available = true;
+			me.version = info.version;
+			channel.onSWORDReady.fire();
+		},function(e) {
+			me.available = false;
+			utils.alert("[ERROR] Error initializing SWORD: " + e);
+		});
+	});
+}
+
+
+SWORD.prototype.CATEGORY_BIBLES       = "Biblical Texts";
+SWORD.prototype.CATEGORY_COMMENTARIES = "Commentaries";
+SWORD.prototype.CATEGORY_LEXDICTS     = "Lexicons / Dictionaries";
+SWORD.prototype.CATEGORY_GENBOOKS     = "Generic Books";
+SWORD.prototype.CATEGORY_DAILYDEVOS   = "Daily Devotional";
+
+
+SWORD.prototype.init = function(successCallback, errorCallback) {
+	exec(successCallback, errorCallback, "SWORD", "init", []);
+};
+
+
+module.exports = new SWORD();
+
+




More information about the sword-cvs mailing list