Procházet zdrojové kódy

included userinfo in template

mk200789 před 10 roky
revize
0ec00d2ca4
100 změnil soubory, kde provedl 11093 přidání a 0 odebrání
  1. 10 0
      .hgignore
  2. 127 0
      README.md
  3. 22 0
      angular/bower.json
  4. 20 0
      angular/index.html
  5. 5 0
      angular/partials/snippets.partial.html
  6. 16 0
      angular/scripts/app.js
  7. 13 0
      angular/scripts/controllers/appController.js
  8. 10 0
      angular/scripts/controllers/restAppController.js
  9. 12 0
      angular/scripts/factories/restAppFactory.js
  10. 20 0
      bower.json
  11. 0 0
      hackathon_starter/hackathon/__init__.py
  12. 7 0
      hackathon_starter/hackathon/admin.py
  13. 11 0
      hackathon_starter/hackathon/forms.py
  14. 0 0
      hackathon_starter/hackathon/migrations/__init__.py
  15. 25 0
      hackathon_starter/hackathon/models.py
  16. 0 0
      hackathon_starter/hackathon/scripts/__init__.py
  17. 162 0
      hackathon_starter/hackathon/scripts/github.py
  18. 24 0
      hackathon_starter/hackathon/scripts/linkedin.py
  19. 29 0
      hackathon_starter/hackathon/scripts/steam.py
  20. 147 0
      hackathon_starter/hackathon/scripts/tumblr.py
  21. 11 0
      hackathon_starter/hackathon/scripts/twilioapi.py
  22. 9 0
      hackathon_starter/hackathon/serializers.py
  23. 26 0
      hackathon_starter/hackathon/static/css/form.css
  24. binární
      hackathon_starter/hackathon/static/img/github.png
  25. binární
      hackathon_starter/hackathon/static/img/linkedin.jpg
  26. binární
      hackathon_starter/hackathon/static/img/steam.png
  27. binární
      hackathon_starter/hackathon/static/img/tumblr.png
  28. 16 0
      hackathon_starter/hackathon/templates/hackathon/api_examples.html
  29. 61 0
      hackathon_starter/hackathon/templates/hackathon/base.html
  30. 110 0
      hackathon_starter/hackathon/templates/hackathon/github.html
  31. 14 0
      hackathon_starter/hackathon/templates/hackathon/index.html
  32. 25 0
      hackathon_starter/hackathon/templates/hackathon/linkedin.html
  33. 47 0
      hackathon_starter/hackathon/templates/hackathon/login.html
  34. 40 0
      hackathon_starter/hackathon/templates/hackathon/navbar.html
  35. 42 0
      hackathon_starter/hackathon/templates/hackathon/register.html
  36. 31 0
      hackathon_starter/hackathon/templates/hackathon/steam.html
  37. 76 0
      hackathon_starter/hackathon/templates/hackathon/tumblr.html
  38. 12 0
      hackathon_starter/hackathon/templates/hackathon/twilio.html
  39. 3 0
      hackathon_starter/hackathon/tests.py
  40. 0 0
      hackathon_starter/hackathon/unittests/__init__.py
  41. 8 0
      hackathon_starter/hackathon/unittests/testcase.py
  42. 192 0
      hackathon_starter/hackathon/unittests/testgithub.py
  43. 925 0
      hackathon_starter/hackathon/unittests/teststeam.py
  44. 31 0
      hackathon_starter/hackathon/unittests/testtumblr.py
  45. 17 0
      hackathon_starter/hackathon/urls.py
  46. 162 0
      hackathon_starter/hackathon/views.py
  47. 0 0
      hackathon_starter/hackathon_starter/__init__.py
  48. 116 0
      hackathon_starter/hackathon_starter/settings.py
  49. 8 0
      hackathon_starter/hackathon_starter/urls.py
  50. 14 0
      hackathon_starter/hackathon_starter/wsgi.py
  51. 10 0
      hackathon_starter/manage.py
  52. 3 0
      ionic/.bowerrc
  53. 6 0
      ionic/.gitignore
  54. 7 0
      ionic/bower.json
  55. 49 0
      ionic/config.xml
  56. 50 0
      ionic/gulpfile.js
  57. 83 0
      ionic/hooks/README.md
  58. 94 0
      ionic/hooks/after_prepare/010_add_platform_class.js
  59. 4 0
      ionic/ionic.project
  60. 25 0
      ionic/package.json
  61. 202 0
      ionic/plugins/com.ionic.keyboard/LICENSE
  62. 123 0
      ionic/plugins/com.ionic.keyboard/README.md
  63. 19 0
      ionic/plugins/com.ionic.keyboard/package.json
  64. 55 0
      ionic/plugins/com.ionic.keyboard/plugin.xml
  65. 96 0
      ionic/plugins/com.ionic.keyboard/src/android/IonicKeyboard.java
  66. 135 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/index.js
  67. 222 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/.cproject
  68. 76 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/.project
  69. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/libKeyboard.so
  70. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_reader.o
  71. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_value.o
  72. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_writer.o
  73. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/plugin.o
  74. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/tokenizer.o
  75. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/CallKeyboard.o
  76. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/Logger.o
  77. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/keyboard_js.o
  78. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/keyboard_ndk.o
  79. 19 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/autolink.h
  80. 43 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/config.h
  81. 42 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/features.h
  82. 39 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/forwards.h
  83. 10 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/json.h
  84. 196 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/reader.h
  85. 1069 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/value.h
  86. 174 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/writer.h
  87. 125 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_batchallocator.h
  88. 448 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_internalarray.inl
  89. 607 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_internalmap.inl
  90. 892 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_reader.cpp
  91. 1726 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_value.cpp
  92. 292 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_valueiterator.inl
  93. 829 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_writer.cpp
  94. 320 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/plugin.cpp
  95. 70 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/plugin.h
  96. 222 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/tokenizer.cpp
  97. 55 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/tokenizer.h
  98. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/libKeyboard.so
  99. binární
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/public/json_reader.o
  100. 0 0
      ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/public/json_value.o

+ 10 - 0
.hgignore

@@ -0,0 +1,10 @@
+syntax: glob
+
+.DS_Store
+db.sqlite3
+*.pyc
+bower_components/
+migrations/
+*.coverage
+Thumbs.db
+*/vendor

+ 127 - 0
README.md

@@ -0,0 +1,127 @@
+Django Hackathon Starter
+------------------------
+
+## What is Django Hackathon Starter
+
+> Django Hackathon Starter aims to be a project which will aggegrate data from several APIs, producing a RESTful API which can be consumed by a client (also intended to be built). 
+
+Our deployment can be found [here](http://django-hackathon-starter.herokuapp.com/hackathon/).
+
+## Running this project
+
+In order to run this project, do the following:
+
+    # Install the requirements
+    pip install -r requirements.txt
+
+    # Perform database migrations
+    python manage.py migrate
+
+    # Run the server
+    python manage.py runserver
+
+## Front End dependencies
+
+This project relies on Bower for all front end libraries, to avoid pushing up large libraries such as `jQuery` and `Bootstrap`. To install `bower`, you will need to install `npm`, which now comes bundled with `node.js`. To install `npm`, simply install [node as follows](https://github.com/joyent/node/wiki/installing-node.js-via-package-manager). 
+
+First, install `bower`:
+
+    npm install -g bower
+
+Then:
+
+    # In the same directory as requirements.txt
+    bower install
+
+This will download and extract all the packages listed within `bower.json`. **Under no circumstance should any front-end libraries manually be pushed up to the repository.**
+
+Then:
+
+    # move bower_components into static folder
+    mv bower_components/ hackathon_starter/hackathon/static
+
+To install the front-end dependencies for the AngularJS client, do the following:
+
+    cd public
+    bower install
+    # Rename bower_components folder to vendor
+    mv bower_components/ vendor/
+
+
+## Testing
+
+This project aims to be as close to 100% tested as possible. For a good guide to testing using Python and `Mock`, `Nosetests` and `Unittests` libraries, please [read here](http://docs.python-guide.org/en/latest/writing/tests/).
+
+To run the tests:
+
+    hackthon-starter $ python manage.py test hackathon/unittests/
+
+## Code evaluation
+
+In order to write clean code with a consistent style guide, we'll be using `Pylint` to maintain our code. Pylint will display a ton of messages regarding things that should be fixed. 
+
+
+## RESTful endpoints
+
+Using the `Django REST framework, the current RESTful endpoints exist:
+
+    http://127.0.0.1:8000/hackathon/snippets/
+
+The list will appear empty at first, since the database model `Snippets` will be empty. To populate it with some sample data, run the following:
+
+    python manage.py shell
+    from hackathon.models import Snippet
+    from hackathon.serializers import SnippetSerializer
+    from rest_framework.renderers import JSONRenderer
+    from rest_framework.parsers import JSONParser
+
+    snippet = Snippet(code='foo = "bar"\n')
+    snippet.save()
+
+    snippet = Snippet(code='print "hello, world"\n')
+    snippet.save()
+
+The above will open the Django shell, and allow you to create objects and save them to the database. If you then navigate to the URL above, you will see the JSON output of the database model, `Snippet`. 
+
+## AngularJS Client
+
+As of `April 11th, 2015`, there is now a sample AngularJS client which pulls data from the Django sample API endpoint: `http://127.0.0.1:8000/hackathon/snippets/`. To test it, do the following:
+
+* Within the `public/` directory, run `python -m SimpleHTTPServer 80`. You may need `sudo` on your respective Operating System.
+* Navigate to: `http://localhost/#/snippets`. Here you will see whatever content was stored within the database model, `Snippet`. If nothing shows up, go back to the `RESTful endpoints` step to populate your database with some `Snippet` objects. 
+
+## Ionic Client
+
+As of `April 11th, 2015`, there is now a sample Ionic application which works on iOS. This application pulls data from the Django sample API endpoint: `http://127.0.0.1:8000/hackathon/snippets/`. In order to successfully run this project, you must do the following:
+
+    # Make sure django-hackathon-starter is running
+    python manage.py runserver
+
+    # Install cordova and ionic
+    # On a Mac, you'll need to use sudo
+    npm install -g cordova ionic 
+
+    cd ionic
+
+    # Add support for the iOS platform
+    ionic platform add ios
+
+    # Build the project
+    ionic build ios
+
+Running the final command, `ionic build ios` will generate an `.xcodeproj` file within `platforms/ionic`. You can open it and then run it, which you should then see a list of all the `Snippet` objects from the Django Hackathon Starter database. 
+
+You can also test the project in the browser by doing the following:
+
+    cd ionic
+    ionic serve 
+
+Running `ionic serve` will automatically open up your web browser and run the application.
+
+
+## Contributors
+
+* David Leonard
+* Eswari Swarna
+* Marco Quezada 
+* Wan Kim Mok

+ 22 - 0
angular/bower.json

@@ -0,0 +1,22 @@
+{
+  "name": "django-hackathon-starter",
+  "version": "0.0.0",
+  "authors": [
+    "David Leonard <sephirothcloud1025@yahoo.com>"
+  ],
+  "description": "Django boilerplate project for hackathons",
+  "keywords": [
+    "Django",
+    "Python",
+    "API",
+    "RESTful"
+  ],
+  "license": "MIT",
+  "dependencies": {
+    "bootstrap": "~3.3.4",
+    "jquery": "~2.1.3",
+    "bootstrap-social": "~4",
+    "angular": "~1.3.15",
+    "angular-ui-router": "~0.2.13"
+  }
+}

+ 20 - 0
angular/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en-us" data-ng-app="restApp" data-ng-controller="appController">
+    <head>
+        <meta charset="utf-8">
+
+        <title data-ng-bind="pageTitle + ' | RestAPP'">RestAPP</title>
+
+        <script src="vendor/angular/angular.js"></script>
+        <script src="vendor/angular-ui-router/release/angular-ui-router.min.js"></script>
+
+        <script src="scripts/app.js"></script>
+        <script src="scripts/controllers/appController.js"></script>
+        <script src="scripts/controllers/restAppController.js"></script>
+        <script src="scripts/factories/restAppFactory.js"></script>
+    </head>
+
+    <body>
+        <div data-ui-view></div>
+    </body>
+</html>

+ 5 - 0
angular/partials/snippets.partial.html

@@ -0,0 +1,5 @@
+<div data-ng-repeat="data in restData">
+    <div data-ng-repeat="datum in data track by $index">
+        {{ datum }}
+    </div>
+</div>

+ 16 - 0
angular/scripts/app.js

@@ -0,0 +1,16 @@
+'use strict';
+
+var restApp = angular.module('restApp', [
+    'ui.router'
+])
+.config(function($stateProvider, $urlRouterProvider) {
+    $stateProvider
+        .state('snippets', {
+            url: '/snippets',
+            templateUrl: 'partials/snippets.partial.html',
+            controller: 'restAppController',
+            data: {
+                pageTitle: 'Sample API data'
+            }
+        });
+});

+ 13 - 0
angular/scripts/controllers/appController.js

@@ -0,0 +1,13 @@
+'use strict';
+
+restApp.controller('appController', function($scope, $location) {
+    $scope.siteTitle = 'REST App';
+
+    $scope.$on('$stateChangeSuccess', function(event, toState) {
+        $scope.pageTitle = toState.data.pageTitle;
+    });
+
+    $scope.isActive = function(viewLocation) {
+        return viewLocation === $location.path();
+    };
+});

+ 10 - 0
angular/scripts/controllers/restAppController.js

@@ -0,0 +1,10 @@
+'use strict';
+
+restApp.controller('restAppController', function($scope, restAppFactory) {
+    $scope.restData = {};
+    
+    $scope.restData = restAppFactory.get().success(function(data) {
+    	$scope.restData = data;
+    	console.log(data);
+    });
+});

+ 12 - 0
angular/scripts/factories/restAppFactory.js

@@ -0,0 +1,12 @@
+'use strict';
+
+restApp.factory('restAppFactory', function($http) {
+    return {
+        get: function() {
+            return $http({
+                url: 'http://127.0.0.1:8000/hackathon/snippets/',
+                method: 'GET',
+            });
+        }
+    };
+});

+ 20 - 0
bower.json

@@ -0,0 +1,20 @@
+{
+  "name": "django-hackathon-starter",
+  "version": "0.0.0",
+  "authors": [
+    "David Leonard <sephirothcloud1025@yahoo.com>"
+  ],
+  "description": "Django boilerplate project for hackathons",
+  "keywords": [
+    "Django",
+    "Python",
+    "API",
+    "RESTful"
+  ],
+  "license": "MIT",
+  "dependencies": {
+    "bootstrap": "~3.3.4",
+    "jquery": "~2.1.3",
+    "bootstrap-social": "~4"
+  }
+}

+ 0 - 0
hackathon_starter/hackathon/__init__.py


+ 7 - 0
hackathon_starter/hackathon/admin.py

@@ -0,0 +1,7 @@
+from django.contrib import admin
+from hackathon.models import UserProfile, Profile
+
+# Register your models here.
+admin.site.register(UserProfile)
+admin.site.register(Profile)
+

+ 11 - 0
hackathon_starter/hackathon/forms.py

@@ -0,0 +1,11 @@
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+from django import forms
+from hackathon.models import UserProfile
+
+class UserForm(forms.ModelForm):
+    password = forms.CharField(widget=forms.PasswordInput())
+
+    class Meta:
+        model = User
+        fields = ('username', 'email', 'password')

+ 0 - 0
hackathon_starter/hackathon/migrations/__init__.py


+ 25 - 0
hackathon_starter/hackathon/models.py

@@ -0,0 +1,25 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+# Create your models here.
+class UserProfile(models.Model):
+    # This line is required. Links UserProfile to a User model instance.
+    user = models.OneToOneField(User)
+
+    # Override the __unicode__() method to return out something meaningful!
+    def __unicode__(self):
+        return self.user.username
+
+class Profile(models.Model):
+    user = models.ForeignKey(User)
+    oauth_token = models.CharField(max_length=200)
+    oauth_secret = models.CharField(max_length=200)
+
+class Snippet(models.Model):
+    created = models.DateTimeField(auto_now_add=True)
+    title = models.CharField(max_length=100, blank=True, default='')
+    code = models.TextField()
+    linenos = models.BooleanField(default=False)
+
+    class Meta:
+        ordering = ('created',)

+ 0 - 0
hackathon_starter/hackathon/scripts/__init__.py


+ 162 - 0
hackathon_starter/hackathon/scripts/github.py

@@ -0,0 +1,162 @@
+'''
+Module github.py contains a handful of methods
+for interacting with Github data.
+'''
+
+import requests
+import simplejson as json
+
+########################
+# GITHUB API CONSTANTS #
+########################
+
+API_BASE_URL = 'https://api.github.com/users/DrkSephy'
+
+def getUserData(clientID, clientSecret):
+	'''Get generic Github User data.'''
+	url = API_BASE_URL + '?' + clientID + '&' + clientSecret
+	req = requests.get(url)
+	jsonList = []
+	jsonList.append(json.loads(req.content))
+	parsedData = []
+	userData = {}
+	for data in jsonList: 
+		userData['name'] = data['name']
+		userData['blog'] = data['blog']
+		userData['email'] = data['email']
+		userData['public_gists'] = data['public_gists']
+		userData['public_repos'] = data['public_repos']
+		userData['avatar_url'] = data['avatar_url']
+		userData['followers'] = data['followers']
+		userData['following'] = data['following']
+	parsedData.append(userData)
+
+	return parsedData
+	
+
+def getUserRepositories(clientID, clientSecret):
+	'''Get a list of all repositories owned by a User.'''
+
+	pageNumber = 1
+
+
+	jsonList = []
+	repositories = []
+
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+	
+	for data in jsonList:
+		for datum in data:
+			repositories.append(datum['name'])
+			
+	return repositories
+
+def getForkedRepositories(clientID, clientSecret):
+	'''Get a list of all forked repositories by a user.'''
+	
+	pageNumber = 1
+
+	
+	jsonList = []
+
+	
+	forkedRepositories = []
+ 
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+
+	forkedRepos = {}
+	for data in jsonList:
+		for datum in data:
+			if datum['fork'] == True:
+				forkedRepos['name'] = datum['name']
+				forkedRepositories.append(forkedRepos)
+				forkedRepos = {}
+
+	return forkedRepositories
+
+def getTopContributedRepositories(repos, clientID, clientSecret):
+	'''Get a list of all commits for each repository owned.'''
+
+	jsonList = []
+	for repo in repos:
+		req = requests.get('https://api.github.com/repos/DrkSephy/' + repo + '/stats/contributors' + '?' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+
+	parsedData = []
+
+	indexNumber = -1
+	for item in jsonList:
+		indexNumber += 1
+		commits = {}
+		for data in item:
+			if data['author']['login'] == 'DrkSephy':
+				commits['author'] = data['author']['login']
+				commits['total'] = data['total']
+				commits['repo_name'] = repos[indexNumber]
+				parsedData.append(commits)
+
+	return parsedData
+
+def filterCommits(data):
+	'''Returns the top 10 committed repositories.'''
+
+	maxCommits = []
+	for i in range(1, 10):
+		maxCommitedRepo = max(data, key=lambda x:x['total'])
+		maxCommits.append(maxCommitedRepo)
+		index = data.index(maxCommitedRepo)
+		data.pop(index)
+	return maxCommits
+	
+	
+def getStarGazerCount(clientID, clientSecret):
+	'''Get Stargazer counts for all repositories.'''
+	
+	pageNumber = 1
+	jsonList = []
+	stargazers = []
+	while True:
+		req = requests.get('https://api.github.com/users/DrkSephy/repos?page=' + str(pageNumber) + '&' + clientID + '&' + clientSecret)
+		jsonList.append(json.loads(req.content))
+		if len(json.loads(req.content)) < 30:
+			break
+		elif len(json.loads(req.content)) >= 30:
+			pageNumber += 1
+
+
+	for data in jsonList:
+		for datum in data:
+			starData = {}
+			starData['stargazers_count'] = datum['stargazers_count']
+			starData['name'] = datum['name']
+			stargazers.append(starData)
+			
+	return stargazers
+
+def filterStarGazerCount(data):
+	'''Return top 10 starred repositories.'''
+	maxStars= []
+	for i in range(1, 10):
+		maxStarGazers = max(data, key=lambda x:x['stargazers_count'])
+		maxStars.append(maxStarGazers)
+		index = data.index(maxStarGazers)
+		data.pop(index)
+	return maxStars
+
+
+
+

+ 24 - 0
hackathon_starter/hackathon/scripts/linkedin.py

@@ -0,0 +1,24 @@
+import requests
+import simplejson as json
+
+
+consumer_key    = "7895bbnlh1k0mn"
+consumer_secret = "7CjUx1xTsF2WDRAI"
+oauth_token  	= "60b8f2c4-28b6-498d-a645-9dffb8baf47d"
+oauth_secret	= "3114e3d4-d725-482d-a11c-2e7607025a27"
+
+def getUserInfo():
+	req = requests.get("https://api.linkedin.com/v1/people/~")
+	jlist = []
+	jlist.append(json.loads(req.content))
+	parsedData = []
+	userData = {}
+	for data in jlist: 
+		userData['firstname'] = data['firstname']
+		userData['lasttname'] = data['lastname']
+		userData['email'] = data['email']
+		userData['connections'] = data['connections']
+		
+	parsedData.append(userData)
+
+	return parsedData

+ 29 - 0
hackathon_starter/hackathon/scripts/steam.py

@@ -0,0 +1,29 @@
+# pylint: disable=C0303
+
+import requests
+import json
+
+SteamUN = "Marorin"
+key = '231E98D442E52B87110816C3D5114A1D'
+
+def gamesPulling(steamID,key):
+    # Returns the JSON data from the Steam API based of one's 
+    # Steam ID number and returns a dictionary of gameids and minutes played.
+    steaminfo = {
+        'key': key, 
+        'steamid': steamID,
+        'format':'JSON',
+        'include_appinfo':'1'
+    }
+    r = requests.get('http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/', params=steaminfo)
+    d = json.loads(r.content)
+    return d['response']['games']
+ 
+def steamIDPulling(SteamUN,key):
+    #Pulls out and returns the steam id number for use in steam queries.
+    steaminfo = {'key': key,'vanityurl': SteamUN}
+    a = requests.get('http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/', params=steaminfo)
+    k = json.loads(a.content)
+    SteamID = k['response']['steamid']
+    
+    return SteamID

+ 147 - 0
hackathon_starter/hackathon/scripts/tumblr.py

@@ -0,0 +1,147 @@
+import requests
+import simplejson as json
+import time 
+import urllib
+import re
+from bs4 import BeautifulSoup
+import urlparse
+import oauth2
+
+request_token_url   = 'http://www.tumblr.com/oauth/request_token'
+authorize_url       = 'http://www.tumblr.com/oauth/authorize'
+access_token_url    = 'http://www.tumblr.com/oauth/access_token'
+
+user_uri			= "http://api.tumblr.com/v2/user/info"
+blog_uri			= "http://api.tumblr.com/v2/blog/"
+
+class TumblrOauthClient(object):
+
+	token = None
+	oauth_verifier = None
+	oauth_token = None
+	oauth_token_secret = None
+	accessed = False
+
+
+
+	def __init__(self, consumer_key, consumer_secret):
+		self.consumer_key = consumer_key
+		self.consumer_secret = consumer_secret
+		self.consumer = oauth2.Consumer(consumer_key, consumer_secret)
+		
+
+
+	def authorize_url(self):
+		client = oauth2.Client(self.consumer)
+		resp, content = client.request(request_token_url, "GET")
+		#parse content
+		if not self.oauth_token:
+			request_token = dict(urlparse.parse_qsl(content))
+			self.oauth_token = request_token['oauth_token'] #'QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl' #
+			self.oauth_token_secret = request_token['oauth_token_secret']#'u10SuRl2nzS8vFK4K7UPQexAvbIFBFrZBjA79XDlgoXFxv9ZhO' #
+		link = authorize_url+"?oauth_token="+self.oauth_token+"&redirect_uri=http%3A%2F%2Flocalhost%3A8000/hackathon/tumblr"
+		return link
+
+
+	def access_token_url(self, oauth_verifier=''):
+		self.accessed = True
+		token = oauth2.Token(self.oauth_token, self.oauth_token_secret)
+		self.oauth_verifier = oauth_verifier
+		print self.oauth_verifier
+		token.set_verifier(self.oauth_verifier)
+		client = oauth2.Client(self.consumer, token)
+		resp, content = client.request(access_token_url,"POST")
+		access_token = dict(urlparse.parse_qsl(content))
+		#set verified token
+		self.token = oauth2.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
+		#print self.token
+			
+
+
+	def getUserInfo(self):
+		''' Returns users information. '''
+		client = oauth2.Client(self.consumer, self.token)
+		#print client
+		resp, content = client.request(user_uri, "POST")
+		if int(resp['status']) != 200:
+			raise Exception("Invalid response %s." % resp['status'])
+
+		#return content in json format
+		jsonlist = json.loads(content)
+		response = jsonlist['response']
+		user_info = response['user']
+		total_blogs = len(user_info['blogs'])
+		#print user_info
+		return user_info, total_blogs
+
+
+	def getBlogInfo(self, user):
+		''' Returns blogger's blog information '''
+		blog_info = blog_uri + user + ".tumblr.com/info?api_key="+self.consumer_key
+		req = requests.get(blog_info)
+		
+		#if int(req.status_code) != 200:
+		#	raise Exception("Invalid response %s." % resp['status'])
+		
+
+		jsonlist = json.loads(req.content)
+		response = jsonlist['response']
+		blog 	 = response['blog']
+		blog['updated'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(blog['updated']))
+		return blog
+
+
+	def getTaggedInfo(self, tag):
+		''' Return tags related to blog with certain tag. '''
+
+		tagged_uri = "http://api.tumblr.com/v2/tagged?tag="+tag+"&api_key="+self.consumer_key+"&limit=20"
+		req = requests.get(tagged_uri)
+		jsonlist = json.loads(req.content)
+
+		tags = []
+
+		meta = jsonlist['meta']
+		body = jsonlist['response']
+		for blog in body:
+			for data in blog:
+				if data == "tags":
+					#print blog[data]
+					for i in blog[data]:
+						m = re.match("(.*)(s*)s(t*)t(a*)a(r*)r(b*)b(u*)u(c*)c(k*)k(.*)", i.lower())
+						if not m:
+							tags.append(i)					
+
+		return tags	
+
+
+	def getTaggedBlog(self, tag):
+		''' Return the tagged blogs's captions or post.'''
+		
+		tagged_uri = "http://api.tumblr.com/v2/tagged?tag="+tag+"&api_key="+self.consumer_key+"&limit=20"
+		req = requests.get(tagged_uri)
+		jsonlist = json.loads(req.content)
+		
+		meta = jsonlist['meta']
+		body = jsonlist['response']
+
+		tagtext = []
+
+		for blog in body:
+			#print "####"
+			for data in blog:
+				#post
+				if data == "body":
+					if blog[data]:
+						#print blog[data]
+						soup = BeautifulSoup(blog[data])
+						text = soup.get_text()
+						tagtext.append(text)
+				#an image
+				if data == "caption":
+					if blog[data]:
+						#print blog[data]
+						soup = BeautifulSoup(blog[data])
+						text = soup.get_text()					
+						tagtext.append(text)
+		
+		return tagtext

+ 11 - 0
hackathon_starter/hackathon/scripts/twilioapi.py

@@ -0,0 +1,11 @@
+import twilio
+import requests
+from twilio.rest import TwilioRestClient
+ 
+account_sid = "AC7889a1889c1833bd7181e45e60372776"
+auth_token  = "1ad0315f3cc7a154aaaef048f1304f71"
+client = TwilioRestClient(account_sid, auth_token)
+ 
+def sendSMS(body, to, sender):
+	message = client.messages.create(body=body, to=to, from_=sender) 
+	return

+ 9 - 0
hackathon_starter/hackathon/serializers.py

@@ -0,0 +1,9 @@
+from django.forms import widgets
+from rest_framework import serializers
+from hackathon.models import Snippet
+
+
+class SnippetSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Snippet
+        fields = ('id', 'title', 'code', 'linenos')

+ 26 - 0
hackathon_starter/hackathon/static/css/form.css

@@ -0,0 +1,26 @@
+
+div.well{
+  height: 250px;
+} 
+
+.Absolute-Center {
+  margin: auto;
+  position: absolute;
+  top: 0; left: 0; bottom: 0; right: 0;
+}
+
+.Absolute-Center.is-Responsive {
+  width: 50%; 
+  height: 50%;
+  min-width: 200px;
+  max-width: 400px;
+  padding: 40px;
+}
+
+#logo-container{
+  margin: auto;
+  margin-bottom: 10px;
+  width:200px;
+  height:30px;
+  background-image:url('http://placehold.it/200x30/000000/ffffff/&text=Django+Hackathon+Starter');
+}

binární
hackathon_starter/hackathon/static/img/github.png


binární
hackathon_starter/hackathon/static/img/linkedin.jpg


binární
hackathon_starter/hackathon/static/img/steam.png


binární
hackathon_starter/hackathon/static/img/tumblr.png


+ 16 - 0
hackathon_starter/hackathon/templates/hackathon/api_examples.html

@@ -0,0 +1,16 @@
+<html>
+{% include 'hackathon/base.html' %}
+<body>
+
+
+	<div class="row text-center">
+	    <div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/github/">Github Example</a></div>
+	    <div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/steam/">Steam Example</a></div>
+	    <div class="col-sm-4"><a href={{tumblr_url}}>Tumblr Example</a></div>
+		<div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/linkedin/">LinkedIn Example</a></div>
+		<div class="col-sm-4"><a href="http://127.0.0.1:8000/hackathon/twilio/">Twilio Example</a></div>
+
+  	</div>
+
+</body>
+</html>

+ 61 - 0
hackathon_starter/hackathon/templates/hackathon/base.html

@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title> Django Hackathon Starter </title>
+    <script src="/static/bower_components/jquery/dist/jquery.js"></script>
+    <script type="text/javascript" src="/static/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
+    
+    
+    <link rel="stylesheet" href="/static/bower_components/bootstrap/dist/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/static/bower_components/bootstrap/dist/css/bootstrap-theme.min.css">
+    <link rel="stylesheet" href="/static/bower_components/bootstrap-social/bootstrap-social.css">
+    <link rel="stylesheet" href="/static/bower_components/font-awesome/css/font-awesome.min.css">
+
+  </head>
+    
+  <body>
+    <nav class="navbar navbar-default" role="navigation">
+      <div class="container-fluid">
+        <!-- Brand and toggle get grouped for better mobile display -->
+        <div class="navbar-header">
+          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+            <span class="sr-only">Toggle navigation</span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="navbar-brand" href="/hackathon">Django Hackathon Starter</a>
+      </div>
+
+      <!-- Collect the nav links, forms, and other content for toggling -->
+      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+        <ul class="nav navbar-nav navbar-left">
+          {% if user.is_authenticated %}
+          <li><a href="/hackathon/api">API</a></li>
+          {% endif %}
+        </ul>
+        <ul class="nav navbar-nav navbar-right">
+          {% if not user.is_authenticated %}
+            <li class="active"><a href="/hackathon/register">Register <span class="sr-only">(current)</span></a></li>
+            
+            <li><a href="/hackathon/login">Login</a></li>
+          {% endif %}
+            
+        </ul>
+        
+        <ul  class="nav navbar-nav navbar-right">
+          {% if user.is_authenticated %}
+    
+            <li><a>Hello {{user}}</a></li>
+            <li><a href="/hackathon/logout/">Logout</a></li>
+          {% endif %}
+        </ul>
+          
+          
+          </li>
+         </ul>
+        </div><!-- /.navbar-collapse -->
+      </div><!-- /.container-fluid -->
+    </nav>
+  </body>
+</html>

+ 110 - 0
hackathon_starter/hackathon/templates/hackathon/github.html

@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+    <h1 class="text-center"> Github Resume </h1>
+	<div class="col-lg-12">
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Username <i class="icon-sort"></i></th>
+                <th class="header"> Blog <i class="icon-sort"></i></th>
+                <th class="header"> Public Repos <i class="icon-sort"></i></th>
+                <th class="header"> Public Gists <i class="icon-sort"></i></th>
+                <th class="header"> Email <i class="icon-sort"></i></th>
+                <th class="header"> Followers <i class="icon-sort"></i></th>
+                <th class="header"> Following <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.userData %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                    <td>{{ key.blog }}</td>
+                    <td>{{ key.public_repos }}</td>
+                    <td>{{ key.public_gists }}</td>
+                    <td>{{ key.email }}</td>
+                    <td>{{ key.followers }}</td>
+                    <td>{{ key.following }}</td>
+    			</tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <h2> Top Contributed Repositories </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                <th class="header"> Total <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.filteredData %}
+                <tr>
+                    <td>{{ key.repo_name }}</td>
+                    <td>{{ key.total }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+    <div class="col-xs-4">
+        <h2> Top Starred Repositories </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                <th class="header"> Count <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.filteredStargazers %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                    <td>{{ key.stargazers_count }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+    <div class="col-xs-4">
+        <h2> Contributions </h2>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover table-striped tablesorter">
+                <thead>
+                <tr>
+                <th class="header"> Repository <i class="icon-sort"></i></th>
+                </tr>
+            </thead>
+            <tbody>
+
+            {% for key in data.forkedRepos %}
+                <tr>
+                    <td>{{ key.name }}</td>
+                </tr>
+            {% endfor %}
+
+            </tbody>
+            </table>
+        </div>
+    </div>
+
+</body>
+</html>

+ 14 - 0
hackathon_starter/hackathon/templates/hackathon/index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+
+<html>
+    {% include 'hackathon/base.html' %}
+
+    <body>
+    	{% if user.is_authenticated %}
+        	<h1>Api Example</h1>
+        	<strong>{{ boldmessage }}</strong><br />
+        {% else %}
+        	<h1> Please register/login! </h1>
+        {% endif %}
+    </body>
+</html>

+ 25 - 0
hackathon_starter/hackathon/templates/hackathon/linkedin.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+	<h1>user information</h1>
+	<table>
+	<tr>
+	<th>First name</th>
+	<th>lastname</th>
+	<th>email</th>
+	<th>connection</th>
+	</tr>
+	{% for key in userinfo %}
+    <tr>
+    <td>{{ key.firstname }}</td>
+    <td>{{ key.lastname}}</td>
+    <td>{{ key.email }}</td>
+    <td>{{ key.connectionss }}</td>
+    </tr>
+    {% endfor %}
+
+     </table>
+</body>
+</html>
+

+ 47 - 0
hackathon_starter/hackathon/templates/hackathon/login.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+    {% include 'hackathon/base.html' %}
+    <style>
+      .form-signin {
+        max-width: 550px;
+        padding: 15px;
+        margin: 0 auto;
+      }    
+    </style>
+
+    <body>
+      <div class="container text-center">
+        <form class="form-signin" id="login_form" method="post" action="/hackathon/login/">
+          {% csrf_token %}
+          {% load bootstrap %}
+          <h2 class="form-signin-heading">Login</h2>
+          <br>
+          <input type="text" name="username" class="form-control" placeholder="Username" value="" required autofocus>
+          <br>
+          <input type="password" name="password" class="form-control" placeholder="Password" value=""required>
+          <br>
+          <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
+          <input type="hidden" name="submit" value="submit" />
+        </form>
+      </div>
+
+      <div class="form-signin">
+        <a class="btn btn-block btn-social btn-facebook">
+          <i class="fa fa-facebook"></i>
+          Sign in with Facebook
+        </a>          
+        <a class="btn btn-block btn-social btn-twitter" href="http://127.0.0.1:8000/hackathon/twitter_login/">
+          <i class="fa fa-twitter"></i>
+          Sign in with Twitter
+        </a>
+        <a class="btn btn-block btn-social btn-instagram">
+          <i class="fa fa-instagram"></i>
+          Sign in with Instagram
+        </a>
+        <a class="btn btn-block btn-social btn-google-plus">
+          <i class="fa fa-google-plus"></i>
+          Sign in with Google
+        </a>          
+      </div>
+    </body>
+</html>

+ 40 - 0
hackathon_starter/hackathon/templates/hackathon/navbar.html

@@ -0,0 +1,40 @@
+<body>
+  <nav class="navbar navbar-default" role="navigation">
+      <div class="container-fluid">
+        <!-- Brand and toggle get grouped for better mobile display -->
+        <div class="navbar-header">
+          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+            <span class="sr-only">Toggle navigation</span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="navbar-brand" href="#">Django Hackathon Starter</a>
+      </div>
+
+      <!-- Collect the nav links, forms, and other content for toggling -->
+      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+        <ul class="nav navbar-nav navbar-right">
+          {% if not user.is_authenticated %}
+            <li class="active"><a href="/hackathon/register">Register <span class="sr-only">(current)</span></a></li>
+            
+            <li><a href="/hackathon/login">Login</a></li>
+          {% endif %}
+            
+        </ul>
+        
+        <ul  class="nav navbar-nav navbar-right">
+          {% if user.is_authenticated %}
+    
+            <li><a>Hello {{user}}</a></li>
+            <li><a href="/hackathon/logout/">Logout</a></li>
+          {% endif %}
+        </ul>
+          
+          
+          </li>
+        </ul>
+      </div><!-- /.navbar-collapse -->
+    </div><!-- /.container-fluid -->
+  </nav>
+</body>

+ 42 - 0
hackathon_starter/hackathon/templates/hackathon/register.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+    {% include 'hackathon/base.html' %}
+    <link rel="stylesheet" href="/static/css/form.css">
+    <body>
+        {% if registered %}
+          <strong>Thank you for registering!</strong>
+          <a href="/hackathon/">Return to the homepage.</a><br />
+        
+        {% else %}
+          <div class='container text-center'>
+              <h2 class="form-signin-heading">Sign Up</h2>
+              <br>
+              <form class="form-horizontal" id="user_form" method="post" action="/hackathon/register/"
+                enctype="multipart/form-data">
+                {% csrf_token %}
+                {% load bootstrap %} 
+
+                <table>
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.username | bootstrap_horizontal}}</td>
+                  </tr>
+
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.email | bootstrap_horizontal}}</td>
+                  </tr>
+
+                  <tr>
+                     
+                      <td class="container text-center">{{ user_form.password | bootstrap_horizontal}}</td>
+                  </tr>
+                </table>
+                <button class="btn btn-lg btn-primary" type="submit">Register</button>
+                <input type="hidden" name="submit" value="Register" />
+              </form>
+            </div>
+          {% endif %}
+    </body>
+</html>
+

+ 31 - 0
hackathon_starter/hackathon/templates/hackathon/steam.html

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+	<h1 class="text-center"> Steam API </h1>
+		<div class="col-lg-12">
+	        <div class="table-responsive">
+	            <table class="table table-bordered table-hover table-striped tablesorter">
+	                <thead>
+	                <tr>
+	                <th class="header"> Game ID <i class="icon-sort"></i></th>
+	                <th class="header"> Game Name <i class="icon-sort"></i></th>
+	                <th class="header"> Minutes Played <i class="icon-sort"></i></th>
+	            </thead>
+	            <tbody>
+
+	            {% for game in game %}
+	                <tr>
+	                    <td>{{ game.appid }}</td>
+	                    <td>{{ game.name }}</td>
+	                    <td>{{ game.playtime_forever }}</td>
+	    			</tr>
+	            {% endfor %}
+
+	            </tbody>
+	            </table>
+	        </div>
+	    </div>
+</body>
+</html>

+ 76 - 0
hackathon_starter/hackathon/templates/hackathon/tumblr.html

@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+	<h1 class="text-center"> {{ title }}</h1> 
+	<br>	
+	<div class="col-lg-12">
+		<div class="table-responsive">
+			<h2> BLOGGER </h2>
+			<table class="table table-bordered">
+				<tr>
+					<th>Name</th>
+					<td>{{blogData.name}}</td>
+				</tr>
+				<tr>
+					<th>Posts</th>
+					<td>{{blogData.posts}}</td>				
+				</tr>
+				<tr>
+					<th>Blog title</th>
+					<td>{{blogData.title}}</td>				
+				</tr>
+				<tr>
+					<th>Last updated</th>
+					<td>{{blogData.updated}}</td>				
+				</tr>
+				<tr>
+					<th>Description</th>
+					<td>{{blogData.description}}</td>				
+				</tr>				
+			</table>
+		</div>
+	</div>
+
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> #starbucks </h2>
+			<table class="table table-bordered">
+				{% for i in blogTag %}
+				<tr>
+					<td> {{i}} </td>
+				</tr>
+				{% endfor %}		
+			</table>
+		</div>
+	</div>
+
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> Comments </h2>
+			<table class="table table-bordered">
+				{% for i in blogontag %}
+				<tr>
+					<td> {{i}} </td>
+				</tr>
+				{% endfor %}		
+			</table>
+		</div>
+	</div>
+	<div class="col-md-4">
+		<div class="table-responsive">
+			<h2> User's Info </h2>
+			<table class="table table-bordered">
+				<tr>
+					<th>Name</th>
+					<td>{{userinfo.name}}</td>
+				</tr>	
+				<tr>
+					<th>Total Blogs</th>
+					<td>{{total_blog}}</td>
+				</tr>
+			</table>
+		</div>
+	</div>
+
+</html>

+ 12 - 0
hackathon_starter/hackathon/templates/hackathon/twilio.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+	{% include 'hackathon/base.html' %}
+
+    <h1 class="text-center"> Twilio Messages </h1>
+    {{ context }}
+    </div>
+    
+
+</body>
+</html>

+ 3 - 0
hackathon_starter/hackathon/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 0 - 0
hackathon_starter/hackathon/unittests/__init__.py


+ 8 - 0
hackathon_starter/hackathon/unittests/testcase.py

@@ -0,0 +1,8 @@
+import unittest
+
+def fun(x):
+    return x + 1
+
+class MyTest(unittest.TestCase):
+    def test(self):
+        self.assertEqual(fun(3), 4)

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 192 - 0
hackathon_starter/hackathon/unittests/testgithub.py


+ 925 - 0
hackathon_starter/hackathon/unittests/teststeam.py

@@ -0,0 +1,925 @@
+import unittest
+from mock import Mock, patch, MagicMock
+from django.conf import settings
+from hackathon.scripts.steam import *
+
+
+class SteamTests(unittest.TestCase):
+
+    def setup(self):
+        self.API_URL = 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/'
+        self.APIKEY = '231E98D442E52B87110816C3D5114A1D'
+        self.userID = 'Marorin'
+        self.steamnum = '76561197997115778'
+
+    def testGetUserIDNum(self):
+        '''Test for steam.py method'''
+        
+        # Pulling from setUp
+        userID = self.userID
+        API_URL = self.API_URL
+        APIKEY = self.APIKEY   
+ 
+        # constructing the URL
+        self.url = API_URL + '?' + APIKEY + '&' + userID
+
+        with patch('hackathon.scripts.steam.steamIDpulling') as mock_steamIDPulling:
+            # Mocking the return value of this method.
+            mock_steamIDpulling = 76561197997115778
+            self.assertEqual(steamIDPulling(userID,APIKEY),mock_steamIDpulling)
+
+    def testgamespulling(self):
+        '''Test gamesPulling method'''
+        with patch('hackathon.scripts.steam.gamesPulling) as mock_gamesPulling:
+            jsonList = [{
+				"appid": 4000,
+				"name": "Garry's Mod",
+				"playtime_forever": 0,
+				"img_icon_url": "d9101cbeddcc4ff06c7fa1936c3f381b0bbf2e92",
+				"img_logo_url": "dca12980667e32ab072d79f5dbe91884056a03a2",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 6550,
+				"name": "Devil May Cry 3: Special Edition",
+				"playtime_forever": 217,
+				"img_icon_url": "5c216acd743413bee9ae18c0d5302e5939ca689f",
+				"img_logo_url": "b26ae9eee26c206b2b3bfab7d365f707e20854a3"
+			},
+			{
+				"appid": 10500,
+				"name": "Empire: Total War",
+				"playtime_forever": 0,
+				"img_icon_url": "dc10f7bad53d3d922c196d116b1c5d6a4b274768",
+				"img_logo_url": "d60c77df97439e8434f0d0be9c3e2d9f39699991",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 17460,
+				"name": "Mass Effect",
+				"playtime_forever": 1242,
+				"img_icon_url": "57be81f70afa48c65437df93d75ba167a29687bc",
+				"img_logo_url": "7501ea5009533fa5c017ec1f4b94725d67ad4936"
+			},
+			{
+				"appid": 12810,
+				"name": "Overlord II",
+				"playtime_forever": 0,
+				"img_icon_url": "cc38122745bd44454e7e122e86023fb35e652d9d",
+				"img_logo_url": "7107ed1429c4be7637571fdf262f61af6bc7d4a2"
+			},
+			{
+				"appid": 45700,
+				"name": "Devil May Cry 4",
+				"playtime_forever": 925,
+				"img_icon_url": "1f869ad15ffdc1eb406c5d1635c9c0efb2e91f12",
+				"img_logo_url": "5b274e94aec7806da9a1b5ba5334668781ff0fd2"
+			},
+			{
+				"appid": 24980,
+				"name": "Mass Effect 2",
+				"playtime_forever": 4040,
+				"img_icon_url": "e6f3b9b0762fd4d42a732abfc41887f6c5903a52",
+				"img_logo_url": "d446fe6d77c9f434cd7fd871400b978fc01fb4e7"
+			},
+			{
+				"appid": 4540,
+				"name": "Titan Quest",
+				"playtime_forever": 0,
+				"img_icon_url": "d59f857aed0d38c69960a9d80e3d23e0863f4e01",
+				"img_logo_url": "e82186f6efe8d5d593c2fb1b57f8b1e056e6d82e",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21100,
+				"name": "F.E.A.R. 3",
+				"playtime_forever": 0,
+				"img_icon_url": "01b73115a3ff7315d14f0bcf7beff01ef76162b4",
+				"img_logo_url": "d2fcf83ec76e845ed19f4ff8324304e2981af391",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 620,
+				"name": "Portal 2",
+				"playtime_forever": 29,
+				"img_icon_url": "2e478fc6874d06ae5baf0d147f6f21203291aa02",
+				"img_logo_url": "d2a1119ddc202fab81d9b87048f495cbd6377502",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 45760,
+				"name": "Ultra Street Fighter IV",
+				"playtime_forever": 111,
+				"img_icon_url": "473fcea2eb516528608dff7f9e3e61009d76a282",
+				"img_logo_url": "bdd481249e579f852056b51db32a6279444d4f47",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21090,
+				"name": "F.E.A.R.",
+				"playtime_forever": 0,
+				"img_icon_url": "71f118282be5aaa34eb82506593130ecfcc6a90b",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 21110,
+				"name": "F.E.A.R.: Extraction Point",
+				"playtime_forever": 0,
+				"img_icon_url": "153d4f89ef0bd59a0039c396ff963a31d4d5e71b",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 21120,
+				"name": "F.E.A.R.: Perseus Mandate",
+				"playtime_forever": 0,
+				"img_icon_url": "7b1d0271f2735ca66e1cb681eb4da1a7c985d53f",
+				"img_logo_url": "df122e0ee9eb2a5371910ffda0f8a3382e09232e"
+			},
+			{
+				"appid": 16450,
+				"name": "F.E.A.R. 2: Project Origin",
+				"playtime_forever": 0,
+				"img_icon_url": "6611d8b01c7a2cc3538c478c044d1e09f3140eaa",
+				"img_logo_url": "41734347c3f05fe7dd797570130f5069c08f9d1b"
+			},
+			{
+				"appid": 32800,
+				"name": "The Lord of the Rings: War in the North",
+				"playtime_forever": 0,
+				"img_icon_url": "56dcf3fe99a90c25daae1cbe84319bb8af3c6ac5",
+				"img_logo_url": "b90d899806ebaff87ed7d2cdc4d9e0a3f11b73b0",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 107100,
+				"name": "Bastion",
+				"playtime_forever": 45,
+				"img_icon_url": "8377b4460f19465c261673f76f2656bdb3288273",
+				"img_logo_url": "d113d66ef88069d7d35a74cfaf2e2ee917f61133",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 55230,
+				"name": "Saints Row: The Third",
+				"playtime_forever": 246,
+				"img_icon_url": "ec83645f13643999e7c91da75d418053d6b56529",
+				"img_logo_url": "1129528455a8b297fb6404cbb90e802a62881b11",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 34270,
+				"name": "SEGA Genesis & Mega Drive Classics",
+				"playtime_forever": 4,
+				"img_icon_url": "48a187fa87c58b798646a430d446dd36eeabd1a4",
+				"img_logo_url": "212f55b3ea1a8c70427890896e93a37b49f57187",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71340,
+				"name": "Sonic Generations",
+				"playtime_forever": 520,
+				"img_icon_url": "efda039147f0968bc726c547ff3809f98b69964a",
+				"img_logo_url": "21ec1e24c31a50500bbddb8c8c8add451e6dcbe1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 72850,
+				"name": "The Elder Scrolls V: Skyrim",
+				"playtime_forever": 2431,
+				"img_icon_url": "b9aca8a189abd8d6aaf09047dbb0f57582683e1c",
+				"img_logo_url": "c5af3cde13610fca25cd17634a96d72487d21e74",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 41070,
+				"name": "Serious Sam 3: BFE",
+				"playtime_forever": 0,
+				"img_icon_url": "2e7a17d4b345ffb13ef3d9e39257c2659fe4a86b",
+				"img_logo_url": "cc3a3c30187b5fbbd0a8861ad08b4f7d779ba239",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 57400,
+				"name": "Batman: Arkham City™",
+				"playtime_forever": 1271,
+				"img_icon_url": "4c208d1365ea5614326717ecfcfea1196ef48e70",
+				"img_logo_url": "5456a41d4076244a6c593cbb260c3384493a7727",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 200260,
+				"name": "Batman: Arkham City GOTY",
+				"playtime_forever": 592,
+				"img_icon_url": "746ecf3ce44b2525eb7ad643e76a3b60913d2662",
+				"img_logo_url": "9b229e12fd5ce27bd101d5862c19b1a6e3d01239",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 108710,
+				"name": "Alan Wake",
+				"playtime_forever": 0,
+				"img_icon_url": "ec7953511aaaf5a2c2093b872b5b43c6cab56462",
+				"img_logo_url": "0f9b6613ac50bf42639ed6a2e16e9b78e846ef0a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 207490,
+				"name": "Rayman Origins",
+				"playtime_forever": 585,
+				"img_icon_url": "1e155c2bc13e8793aed8bb61fdac798fe0d49de7",
+				"img_logo_url": "ebfd3f8da2b0416d71724a2929740a72a6eaabf4"
+			},
+			{
+				"appid": 41500,
+				"name": "Torchlight",
+				"playtime_forever": 130,
+				"img_icon_url": "b2a2a43e401dce3c69898b67b1b8af4481d96b08",
+				"img_logo_url": "e36226c6a0575e6e1838e1f915e91f8b31ab3008",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 200710,
+				"name": "Torchlight II",
+				"playtime_forever": 1011,
+				"img_icon_url": "40776762bb63c4eded37d1a2b4431a90aa57ea84",
+				"img_logo_url": "fd37abb86628ff54ed304f75c2fb7cf75a4f6902",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205350,
+				"name": "Mortal Kombat Kollection",
+				"playtime_forever": 0,
+				"img_icon_url": "048e463386c8f0049d6e08bbf8f5ebb5d232394f",
+				"img_logo_url": "44281a64a93a583fdd2435036ac794e7dcc7beb8",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 202750,
+				"name": "Alan Wake's American Nightmare",
+				"playtime_forever": 0,
+				"img_icon_url": "313aabf37ed0b521ad969d3fe21768d31300f1ca",
+				"img_logo_url": "d3593fa14e4ea8685dc6b1f71dbaa980c013ff02",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 113200,
+				"name": "The Binding of Isaac",
+				"playtime_forever": 503,
+				"img_icon_url": "383cf045ca20625db18f68ef5e95169012118b9e",
+				"img_logo_url": "d9a7ee7e07dffed1700cb8b3b9482105b88cc5b5",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 35140,
+				"name": "Batman: Arkham Asylum GOTY Edition",
+				"playtime_forever": 0,
+				"img_icon_url": "e52f91ecb0d3f20263e96fe188de1bcc8c91643e",
+				"img_logo_url": "172e0928b845c18491f1a8fee0dafe7a146ac129",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 211420,
+				"name": "Dark Souls: Prepare to Die Edition",
+				"playtime_forever": 5309,
+				"img_icon_url": "a24804c6c8412c8cd9d50efd06bf03fa58ff80a9",
+				"img_logo_url": "d293c8e38f56de2c7097b2c7a975caca49029a8b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 204300,
+				"name": "Awesomenauts",
+				"playtime_forever": 9,
+				"img_icon_url": "4996933171d0804bd0ceb7b9a0e224b3139d18ba",
+				"img_logo_url": "a2eba6157703c60bfcc199f06df5f1568c9835bb",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 204630,
+				"name": "Retro City Rampage™ DX",
+				"playtime_forever": 0,
+				"img_icon_url": "423b87d4a5a00ff6e807558e565b0b515fadf61b",
+				"img_logo_url": "3ca51d2767c5de3358c4f1824f1b362a9494983f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 214560,
+				"name": "Mark of the Ninja",
+				"playtime_forever": 1,
+				"img_icon_url": "220f33169c93c2f6381cd785399fb52bfc79309f",
+				"img_logo_url": "c20501309696e5bcda98e9e4f2649abc5720a1d1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 49520,
+				"name": "Borderlands 2",
+				"playtime_2weeks": 24,
+				"playtime_forever": 7526,
+				"img_icon_url": "a3f4945226e69b6196074df4c776e342d3e5a3be",
+				"img_logo_url": "86b0fa5ddb41b4dfff7df194a017f3418130d668",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205950,
+				"name": "Jet Set Radio",
+				"playtime_forever": 644,
+				"img_icon_url": "884cfa9f5f615e297f8c53a2010f1b63835e44b5",
+				"img_logo_url": "3272dfd2e30df5629bfbaa851ea503e9ee28b75a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 213610,
+				"name": "Sonic Adventure™ 2 ",
+				"playtime_forever": 0,
+				"img_icon_url": "0ff2b133493b0bf7f1c16a38a83e7053f0b90f2d",
+				"img_logo_url": "b59ee5bd744212a79db6fd8f71aec6729671da2b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 205790,
+				"name": "Dota 2 Test",
+				"playtime_forever": 20,
+				"img_icon_url": "",
+				"img_logo_url": ""
+			},
+			{
+				"appid": 218680,
+				"name": "Scribblenauts Unlimited",
+				"playtime_forever": 0,
+				"img_icon_url": "e933a9993b7d0b905dbb37636a97339a2c277e0f",
+				"img_logo_url": "c3f8420cd87dd772df8a35013e3538e964ecc2b8",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 223220,
+				"name": "Giana Sisters: Twisted Dreams",
+				"playtime_forever": 115,
+				"img_icon_url": "ac543243f2541e7a7728bf2165c5f3ebc57679fb",
+				"img_logo_url": "9c8baddbab7938b5b995843d36526a30bd12bb1d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4920,
+				"name": "Natural Selection 2",
+				"playtime_forever": 0,
+				"img_icon_url": "df709ad4689cbfb82c2971be4adba431e755875f",
+				"img_logo_url": "ab7b1142e17865e6d3472d3fd4b345620ec5f36f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 219950,
+				"name": "NiGHTS into Dreams...",
+				"playtime_forever": 0,
+				"img_icon_url": "630fb86750aaa5d9ca713df086fa93d9804e9f02",
+				"img_logo_url": "7316d46b1ce35a260ddedc6a1f7590a8b98dea92",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4560,
+				"name": "Company of Heroes",
+				"playtime_forever": 0,
+				"img_icon_url": "64946619217da497c9b29bc817bb40dd7d28c912",
+				"img_logo_url": "e12e8695c6766b47a089351dd9c4531e669c2a7b"
+			},
+			{
+				"appid": 9340,
+				"name": "Company of Heroes: Opposing Fronts",
+				"playtime_forever": 0,
+				"img_icon_url": "29725d719946c3e1aa4eea15d262c9fd789c1392",
+				"img_logo_url": "830c99099ea2cfecfe74c41f376fc892a09dd181"
+			},
+			{
+				"appid": 20540,
+				"name": "Company of Heroes: Tales of Valor",
+				"playtime_forever": 0,
+				"img_icon_url": "64946619217da497c9b29bc817bb40dd7d28c912",
+				"img_logo_url": "ed0c55412acea558d025a3e238e2b7341edc5c41"
+			},
+			{
+				"appid": 43110,
+				"name": "Metro 2033",
+				"playtime_forever": 0,
+				"img_icon_url": "a70fe6dc214f24107d20596f3040dbfa220ed42d",
+				"img_logo_url": "df9a163ac1f28dfc84c93a6fc0dc51719eaef518",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 50620,
+				"name": "Darksiders",
+				"playtime_forever": 925,
+				"img_icon_url": "e429cee10d864faf2aae2ea9cd75e8e1942fbe08",
+				"img_logo_url": "14bd29bc9b291081b63258e3bfbbf5bb655c2347",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 55110,
+				"name": "Red Faction: Armageddon",
+				"playtime_forever": 0,
+				"img_icon_url": "e59c7e741c05c9071176b270bdbb733afe55c751",
+				"img_logo_url": "19f894d0e08dff8e284d4facc5968a1025da997d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 228200,
+				"name": "Company of Heroes (New Steam Version)",
+				"playtime_forever": 0,
+				"img_icon_url": "df92dc239acb3cf5d3e3eba645f3df2aaf7f91ad",
+				"img_logo_url": "87aa009e93d5aa56a55d0e9056708d018ddd6483",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 201790,
+				"name": "Orcs Must Die! 2",
+				"playtime_forever": 0,
+				"img_icon_url": "fabd8658e8e76f7c99c56f26b69d29882756f9b4",
+				"img_logo_url": "c345d9b205f349f0e7f4e6cdf8af4d0b7d242505",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 4570,
+				"name": "Warhammer 40,000: Dawn of War - Game of the Year Edition",
+				"playtime_forever": 5,
+				"img_icon_url": "a4c7a8cce43d797c275aaf601d6855b90ba87769",
+				"img_logo_url": "2068980dca52521b069abc109f976d72ba0b1651",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71230,
+				"name": "Crazy Taxi",
+				"playtime_forever": 0,
+				"img_icon_url": "e71b220f8103e3515bd56de6a42395121e31e2cf",
+				"img_logo_url": "be180e020c4e1ca0a13ec1a9006a1235b6a9eb50",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71240,
+				"name": "SEGA Bass Fishing",
+				"playtime_forever": 0,
+				"img_icon_url": "fac67362e11293a673158e6d3c8c67693816868f",
+				"img_logo_url": "6255f428036c011b325b40ebf1c53daa4db7e1f1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71250,
+				"name": "Sonic Adventure DX",
+				"playtime_forever": 0,
+				"img_icon_url": "6568d25b43e2d1d07fc16cbe3ac9278ca51c2fb3",
+				"img_logo_url": "e8374c63e76724af4648cdea5331f4ae39af4d06",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 71260,
+				"name": "Space Channel 5: Part 2",
+				"playtime_forever": 366,
+				"img_icon_url": "82aec5f26e9d40c5275b1cd9bf692c4057c108ef",
+				"img_logo_url": "fad43b313c2f6869c42bf0d7c4959363c5394d9a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 50650,
+				"name": "Darksiders II",
+				"playtime_forever": 1591,
+				"img_icon_url": "a2d5549090144f1bfd9e00f1b460c1ad0aa9c366",
+				"img_logo_url": "b0b8edfa57f332dc529c04b4dd2f5475227e71ac",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 35720,
+				"name": "Trine 2",
+				"playtime_forever": 0,
+				"img_icon_url": "061ecbbd7c70ae1c052377bad136c7759cbb708d",
+				"img_logo_url": "7d7c3b93bd85ad1db2a07f6cca01a767069c6407",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 226320,
+				"name": "Marvel Heroes 2015",
+				"playtime_forever": 0,
+				"img_icon_url": "a0c1c35208af7b63759361305631da48539d45cc",
+				"img_logo_url": "7121a66719963c4790d6169d38b9c65ad8f238bc",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 225260,
+				"name": "Brütal Legend",
+				"playtime_forever": 0,
+				"img_icon_url": "e3f25fba8538e5fb1ead751e767c2774df4fb0b4",
+				"img_logo_url": "cc8b60ac1fa649c950ff7a9881b98709b8372f94",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 210770,
+				"name": "Sanctum 2",
+				"playtime_forever": 0,
+				"img_icon_url": "4cdfa1d19be460374a111b718ce3a204f21ea1dc",
+				"img_logo_url": "333a8c65480bb85148bb3a185843a8520ae5d90f",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 234710,
+				"name": "Poker Night 2",
+				"playtime_forever": 7,
+				"img_icon_url": "b3073e6f089447a9cf1eeabf7579600061546322",
+				"img_logo_url": "0b274bb5ade23104ce267a05ce7ac0f7aaa0248d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 31100,
+				"name": "Wallace & Gromit Ep 1: Fright of the Bumblebees",
+				"playtime_forever": 0,
+				"img_icon_url": "1c8b457c265e36e6ac08d8d5ae5709124eae3025",
+				"img_logo_url": "6b303e67e65d39cd3747ed21efb42de9ddb0d251"
+			},
+			{
+				"appid": 31110,
+				"name": "Wallace & Gromit Ep 2: The Last Resort",
+				"playtime_forever": 0,
+				"img_icon_url": "e6d415690e4c05b3d716030984346442f10e87e9",
+				"img_logo_url": "7cda224cf65955e5e763ce8eff0b099add72f04e"
+			},
+			{
+				"appid": 31120,
+				"name": "Wallace & Gromit Ep 3: Muzzled!",
+				"playtime_forever": 0,
+				"img_icon_url": "70475b4d75934174a0fff9969315be9a4993c150",
+				"img_logo_url": "3910a6ff5e48c5f7ed249b48387bc321504db73c"
+			},
+			{
+				"appid": 31130,
+				"name": "Wallace & Gromit Ep 4: The Bogey Man",
+				"playtime_forever": 0,
+				"img_icon_url": "9072b2096b4542529aa47f4115bff48ab781ff6e",
+				"img_logo_url": "8a5313cf2bdd01a0516c56b3ce952428de85d430"
+			},
+			{
+				"appid": 31220,
+				"name": "Sam & Max 301: The Penal Zone",
+				"playtime_forever": 335,
+				"img_icon_url": "2c9c4ac6dfa50c4c479b6b436f04974a372588f7",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31230,
+				"name": "Sam & Max 302: The Tomb of Sammun-Mak",
+				"playtime_forever": 72,
+				"img_icon_url": "e83fbb799f46b349586ca55fcf612350cc88ffe7",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31240,
+				"name": "Sam & Max 303: They Stole Max's Brain!",
+				"playtime_forever": 0,
+				"img_icon_url": "bf1ebfe347a80e2ac31577e0569de3aa201cd17f",
+				"img_logo_url": "517196c999fe6316134332e749782154bde9adf5"
+			},
+			{
+				"appid": 31250,
+				"name": "Sam & Max 304: Beyond the Alley of the Dolls",
+				"playtime_forever": 0,
+				"img_icon_url": "d4f834ac9d48cd59645f453d0cb30655dee6f629",
+				"img_logo_url": "62ef5af2ce55bb787ff490126c110c41131043bc"
+			},
+			{
+				"appid": 31260,
+				"name": "Sam & Max 305: The City that Dares not Sleep",
+				"playtime_forever": 0,
+				"img_icon_url": "9e41c6d0c777cd0a7fb4e96da4f20d2227841725",
+				"img_logo_url": "62ef5af2ce55bb787ff490126c110c41131043bc"
+			},
+			{
+				"appid": 31270,
+				"name": "Puzzle Agent",
+				"playtime_forever": 0,
+				"img_icon_url": "d0cae0b07b2512302968bd7625a9bf12cebdfba8",
+				"img_logo_url": "f1bd7dd0bae1026b17c61a605a567ed68e683fef"
+			},
+			{
+				"appid": 31280,
+				"name": "Poker Night at the Inventory",
+				"playtime_forever": 0,
+				"img_icon_url": "7d50bd1f5e7cfe68397e9ca0041836ad18153dfb",
+				"img_logo_url": "d962cde096bca06ee10d09880e9f3d6257941161",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 31290,
+				"name": "Back to the Future: Ep 1 - It's About Time",
+				"playtime_forever": 0,
+				"img_icon_url": "a9a9b1683209e3223779ad2315e4bf03e27619d7",
+				"img_logo_url": "252a22c149c29a2d93fcb0080f3ee9d2dbbd9a2f"
+			},
+			{
+				"appid": 94500,
+				"name": "Back to the Future: Ep 2 - Get Tannen!",
+				"playtime_forever": 0,
+				"img_icon_url": "d5382aedd7594e088a078341034e4b369210ec9a",
+				"img_logo_url": "ae0d863314d6111e6debaef7c9cdcf2940738b1e"
+			},
+			{
+				"appid": 94510,
+				"name": "Back to the Future: Ep 3 - Citizen Brown",
+				"playtime_forever": 0,
+				"img_icon_url": "a51c4795b44f689628bd76bc64cad310385ba1a2",
+				"img_logo_url": "7fe46585ad7fbc8fedb38db7f8dd8608be5a46ee"
+			},
+			{
+				"appid": 94520,
+				"name": "Back to the Future: Ep 4 - Double Visions",
+				"playtime_forever": 0,
+				"img_icon_url": "5a7fd98c15742b9fca4e443b5eaadf953a6c83d3",
+				"img_logo_url": "ac9fc7c15ae656d200299003ce22ab84185e54e4"
+			},
+			{
+				"appid": 94530,
+				"name": "Back to the Future: Ep 5 - OUTATIME",
+				"playtime_forever": 0,
+				"img_icon_url": "3d034831533383bc5a58787763925660684de8c4",
+				"img_logo_url": "76361dfc1ef09dbb7f6572a6da7ab38a811f54af"
+			},
+			{
+				"appid": 94590,
+				"name": "Puzzle Agent 2",
+				"playtime_forever": 0,
+				"img_icon_url": "d558eb6bddeb55f5f145822f3949ab50bc02aff9",
+				"img_logo_url": "b7aac2e076fb1c5178681e2cab0f8bae4380c96d",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 94600,
+				"name": "Hector: Ep 1",
+				"playtime_forever": 0,
+				"img_icon_url": "aa0a113e80b8cdeff47a523a87dd2fad1f43d73e",
+				"img_logo_url": "fae3324a5c43647dda98be23bf1db4480c031273"
+			},
+			{
+				"appid": 94610,
+				"name": "Hector: Ep 2",
+				"playtime_forever": 0,
+				"img_icon_url": "0bfad503074efc1c46755d05d36be4755945f8fe",
+				"img_logo_url": "52a3e61842a22bf75f6bf6d355400d5b3776f9b4"
+			},
+			{
+				"appid": 94620,
+				"name": "Hector: Ep 3",
+				"playtime_forever": 0,
+				"img_icon_url": "aa0a113e80b8cdeff47a523a87dd2fad1f43d73e",
+				"img_logo_url": "97ec609986c7672a3928e7dca14d9aead4cbf65f"
+			},
+			{
+				"appid": 236090,
+				"name": "Dust: An Elysian Tail",
+				"playtime_forever": 563,
+				"img_icon_url": "3779535aba1ad565d504a7d52c6dd5c9eeb47fb2",
+				"img_logo_url": "544fd60b00696d8c3402828da7055fea64d619ca",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 229480,
+				"name": "Dungeons & Dragons: Chronicles of Mystara",
+				"playtime_forever": 91,
+				"img_icon_url": "270699bf34b75a6789370de8b0cb98e163832f71",
+				"img_logo_url": "cb7b16b064562469c375a22d9d07a7ab11abdab6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 208610,
+				"name": "Skullgirls ∞Endless Beta∞",
+				"playtime_forever": 292,
+				"img_icon_url": "7bf859db736b8825045b0cc79acc4bb7be8cd7b9",
+				"img_logo_url": "33974b81779c888b3b4d9c4b91d86ef0907b11f3",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 237110,
+				"name": "Mortal Kombat Komplete Edition",
+				"playtime_forever": 365,
+				"img_icon_url": "3b9c627b90f42cf650d5848e2fdd779fa4e6eb19",
+				"img_logo_url": "307dc1eacffd54e5a7a02b663cec1c5105059811",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 245170,
+				"name": "Skullgirls",
+				"playtime_forever": 1152,
+				"img_icon_url": "7bf859db736b8825045b0cc79acc4bb7be8cd7b9",
+				"img_logo_url": "ca3f7bd4fbb3cf73855ebce91b6dafc2104d651b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222940,
+				"name": "THE KING OF FIGHTERS XIII STEAM EDITION",
+				"playtime_forever": 322,
+				"img_icon_url": "de8d9bf86ae8983464d69743b55cef3992330ccf",
+				"img_logo_url": "9f2bec35f18bfc1a80ffab64bc51a09a880343b6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 250760,
+				"name": "Shovel Knight",
+				"playtime_forever": 1,
+				"img_icon_url": "9b8866653bcaf20db1424653df8560205939cdba",
+				"img_logo_url": "23fca16e3df2ed731136574b320988406eb0f712",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 250900,
+				"name": "The Binding of Isaac: Rebirth",
+				"playtime_forever": 95,
+				"img_icon_url": "16d46c8630499bfc54d20745ac90786a302cd643",
+				"img_logo_url": "c7a76988c53e7f3a3aa1cf224aaf4dbd067ebbf9",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 111900,
+				"name": "Guardians of Middle-earth",
+				"playtime_forever": 0,
+				"img_icon_url": "5ab636ac90b8476892d6e0ae377624d5b934f600",
+				"img_logo_url": "08a7116bebd1bf44bb8e86495358dca14224d223",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 234670,
+				"name": "NARUTO SHIPPUDEN: Ultimate Ninja STORM 3 Full Burst",
+				"playtime_forever": 1405,
+				"img_icon_url": "ddd956cc6ec3370449f96298653d4119c5666fff",
+				"img_logo_url": "12895039c12ec92be72faa2d13acb88886b8cb97",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 42910,
+				"name": "Magicka",
+				"playtime_forever": 0,
+				"img_icon_url": "0eb97d0cd644ee08b1339d2160c7a6adf2ea0a65",
+				"img_logo_url": "8c59c674ef40f59c3bafde8ff0d59b7994c66477",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 212480,
+				"name": "Sonic & All-Stars Racing Transformed",
+				"playtime_forever": 0,
+				"img_icon_url": "95767af7b08d7ecebf1e9cb1ed1c92c98e4c084f",
+				"img_logo_url": "351603b89e1863831c84aacab7bf3a315f03443b",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 261640,
+				"name": "Borderlands: The Pre-Sequel",
+				"playtime_2weeks": 838,
+				"playtime_forever": 1157,
+				"img_icon_url": "af5ef05eac8b1eb618e4f57354ac7b3e918ab1bd",
+				"img_logo_url": "df64c72fd335a03dbcc0a19b1f81acc8db1b94ba",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 39150,
+				"name": "FINAL FANTASY VIII",
+				"playtime_forever": 119,
+				"img_icon_url": "e2b0371cd72160603e7ecaaf95b238a46ba254e6",
+				"img_logo_url": "0c912769e975586cdcfe4a6b008d538f1f96a032",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 235460,
+				"name": "METAL GEAR RISING: REVENGEANCE",
+				"playtime_forever": 1268,
+				"img_icon_url": "ad0f84fe48b57f3861b6c6d743f26b98d670c21f",
+				"img_logo_url": "a21384421dafa03783e3672a5f4754f70e63235e",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 550,
+				"name": "Left 4 Dead 2",
+				"playtime_forever": 0,
+				"img_icon_url": "7d5a243f9500d2f8467312822f8af2a2928777ed",
+				"img_logo_url": "205863cc21e751a576d6fff851984b3170684142",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 236430,
+				"name": "DARK SOULS™ II",
+				"playtime_forever": 8872,
+				"img_icon_url": "8d5b3da903efb047d4efb670c08714a4d1071e83",
+				"img_logo_url": "d16871e0aa9196e5e7d865f76fbed278a0309e85",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 282900,
+				"name": "Hyperdimension Neptunia Re;Birth1",
+				"playtime_forever": 1647,
+				"img_icon_url": "0cd228210df4f44ef8e77f62b18d1a9af81a72d4",
+				"img_logo_url": "c2835cfa39dbaf8e7e1f668e4bf491855a274947",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 254700,
+				"name": "resident evil 4 / biohazard 4",
+				"playtime_forever": 737,
+				"img_icon_url": "535bfea3332662271f1e3a972832bc0b4aba5a38",
+				"img_logo_url": "532d72710af44f29cc123c5796e95e0382461ee5",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 231430,
+				"name": "Company of Heroes 2",
+				"playtime_forever": 0,
+				"img_icon_url": "9efafff369d37ea19c44139de4476e6c63319b6b",
+				"img_logo_url": "2c413e4cc731862e0b3307ed9c23b1cd20087130",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 317170,
+				"name": "Company of Heroes 2 - Beta",
+				"playtime_forever": 0,
+				"img_icon_url": "9efafff369d37ea19c44139de4476e6c63319b6b",
+				"img_logo_url": "62afc50b5f0970c1070951f56a7dd0c0b943b013",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 294810,
+				"name": "BlazBlue: Continuum Shift Extend",
+				"playtime_forever": 82,
+				"img_icon_url": "244644a6721480f40e4de61e4bb7a337d999e435",
+				"img_logo_url": "b7105e9443e1f3bed7bb3fd1599a140e75dcf2c6",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 294860,
+				"name": "Valkyria Chronicles™",
+				"playtime_forever": 65,
+				"img_icon_url": "176c6dcafc9bf0fbb87f9adeb224df88c8248a66",
+				"img_logo_url": "08316e1d6a45d8e13de7f5e1a1480cf4efff15cf",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 285440,
+				"name": "Crimzon Clover  WORLD IGNITION",
+				"playtime_forever": 8,
+				"img_icon_url": "8f4f6490c9b48e8d6e2b688c4a097f9bdd8fb56d",
+				"img_logo_url": "72ab0aac6800b9ec9f79571d6f425f0e687d04ca",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 314030,
+				"name": "Guilty Gear X2 #Reload",
+				"playtime_forever": 99,
+				"img_icon_url": "bde7b6e8d891b310fad62d25a0cf009c979db84c",
+				"img_logo_url": "94edca39fa971bc8beeb0066afc99993246a9976"
+			},
+			{
+				"appid": 206420,
+				"name": "Saints Row IV",
+				"playtime_forever": 205,
+				"img_icon_url": "b5e8448a3e2ea31ddf3595addae4e1eee2375c0d",
+				"img_logo_url": "49d796621c286130a8ddeea918d9aae8c8441455",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 21690,
+				"name": "Resident Evil 5 / Biohazard 5",
+				"playtime_forever": 782,
+				"img_icon_url": "26108f5caff3638c9f522dd79ee84a12761f373a",
+				"img_logo_url": "e277ab70fff98bb2300a39bf8e2371a746fe50b1",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222480,
+				"name": "Resident Evil Revelations / Biohazard Revelations UE",
+				"playtime_forever": 476,
+				"img_icon_url": "5725845fe83f846a04135034c5be55aef008c725",
+				"img_logo_url": "cf242207e0e06251f55baf2f89c37ded12c79329",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 323470,
+				"name": "DRAGON BALL XENOVERSE",
+				"playtime_2weeks": 24,
+				"playtime_forever": 815,
+				"img_icon_url": "810b2bab6e3197b5d63d3abffcebafaac8dc6312",
+				"img_logo_url": "f8724eeddf94534d66b8057cf770a9cd8318a14a",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 730,
+				"name": "Counter-Strike: Global Offensive",
+				"playtime_forever": 62,
+				"img_icon_url": "69f7ebe2735c366c65c0b33dae00e12dc40edbe4",
+				"img_logo_url": "d0595ff02f5c79fd19b06f4d6165c3fda2372820",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 222440,
+				"name": "THE KING OF FIGHTERS 2002 UNLIMITED MATCH",
+				"playtime_2weeks": 1,
+				"playtime_forever": 1,
+				"img_icon_url": "c9235efbfa66ad95a6ece092a7860ca8b92cfa6f",
+				"img_logo_url": "787a8b76a5c9348784f50798403b2672e488c557",
+				"has_community_visible_stats": true
+			},
+			{
+				"appid": 247000,
+				"name": "Talisman: Digital Edition",
+				"playtime_forever": 0,
+				"img_icon_url": "ab50e24b04d5fa8faf219fe622199061b57bcf20",
+				"img_logo_url": "73b7daee45a29a5dfe5c0efef72223943bf8722f",
+				"has_community_visible_stats": true
+			}]
+        self.assertEqual(gamesPulling(steamnum,APIKEY),jsonList)

+ 31 - 0
hackathon_starter/hackathon/unittests/testtumblr.py

@@ -0,0 +1,31 @@
+import unittest
+from mock import Mock, patch, MagicMock
+from hackathon.scripts.tumblr import *
+import oauth2
+import urlparse
+from django.conf import settings
+
+class TestTumblr(unittest.TestCase):
+
+	def setUp(self):
+		self.consumer_key = 'KrSbAc9cYLmIgVAn1D21FjRR97QWsutNMxkPDFBxo8CMWtMk4M'
+		self.consumer_secret = 'lKWMtL2Lj8zr5pY51PVqT8ugeoG0DjrdgoFewM0QTSyJ12jP8d'
+		self.consumer = oauth2.Consumer(key=self.consumer_key, secret=self.consumer_secret)
+		self.tumblrclient = TumblrOauthClient(self.consumer_key, self.consumer_secret, 'QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl')
+		self.authorize = self.tumblrclient.get_authorize_url()
+
+		
+	def test_init(self):
+		self.assertEqual(self.consumer.key, self.consumer_key)
+		self.assertEqual(self.consumer.secret, self.consumer_secret)
+
+	def test_get_authorize_url(self):
+		self.client = oauth2.Client(self.consumer)
+		self.assertEqual(self.client.consumer, self.consumer)
+		with patch('hackathon.scripts.tumblr.TumblrOauthClient.get_authorize_url') as mock_get_authorize_url:
+			mock_get_authorize_url.return_value = "oauth_token=QBXdeeMKAnLzDbIG7dDNewTzRYyQoHZLbcn3bAFTCEFF5EXurl&oauth_token_secret=u10SuRl2nzS8vFK4K7UPQexAvbIFBFrZBjA79XDlgoXFxv9ZhO&oauth_callback_confirmed=true"
+			self.request_token = dict(urlparse.parse_qsl(mock_get_authorize_url.return_value))
+			self.oauth_token = self.request_token['oauth_token']
+			self.oauth_token_secret = self.request_token['oauth_token_secret']		
+			link = "http://www.tumblr.com/oauth/authorize?oauth_token="+self.oauth_token+"&redirect_uri=http%3A%2F%2Flocalhost%3A8000/hackathon/tumblr"
+			self.assertEqual(self.authorize,link )

+ 17 - 0
hackathon_starter/hackathon/urls.py

@@ -0,0 +1,17 @@
+from django.conf.urls import patterns, url
+
+from hackathon import views
+
+urlpatterns = patterns('',
+    url(r'^$', views.index, name='index'),
+    url(r'^register/$', views.register, name='register'),
+    url(r'^login/$', views.user_login, name='login'),
+    url(r'^logout/$', views.user_logout, name='logout'),
+    url(r'^api/$', views.api_examples, name='api'),
+    url(r'^steam/$', views.steam, name='steam'),
+    url(r'^github/$', views.github, name='github'),
+    url(r'^tumblr/$', views.tumblr, name='tumblr'),
+    url(r'^linkedin/$', views.linkedin, name='linkedin'),
+    url(r'^snippets/$', views.snippet_list, name='snippets'),
+    url(r'^twilio/$', views.twilio, name="twilio"),
+)

+ 162 - 0
hackathon_starter/hackathon/views.py

@@ -0,0 +1,162 @@
+# Django
+from django.shortcuts import render
+from django.contrib.auth import logout
+from django.template import RequestContext, loader
+from django.contrib.auth import authenticate, login
+from django.http import HttpResponse, HttpResponseRedirect
+from django.conf import settings
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.models import User
+from django.contrib.auth.decorators import login_required
+from django.views.decorators.csrf import csrf_exempt
+from django.http import JsonResponse
+
+# Scripts
+from scripts.steam import gamesPulling, steamIDPulling 
+from scripts.github import *
+from scripts.tumblr import TumblrOauthClient
+from scripts.twilioapi import *
+
+# Python
+import oauth2 as oauth
+from rest_framework.renderers import JSONRenderer
+from rest_framework.parsers import JSONParser
+
+# Models
+from hackathon.models import Snippet
+from hackathon.serializers import SnippetSerializer
+from hackathon.forms import UserForm
+
+
+getTumblr = TumblrOauthClient(settings.TUMBLR_CONSUMER_KEY, settings.TUMBLR_CONSUMER_SECRET)
+
+def index(request):
+    context = {'hello': 'world'}
+    return render(request, 'hackathon/index.html', context)
+
+def twilio(request):
+    sendSMS('Meow', '+13473282978', '+13473781813')
+    return render(request, 'hackathon/twilio.html')
+
+def api_examples(request):
+    if not getTumblr.accessed:
+        obtain_oauth_verifier = getTumblr.authorize_url()
+    else:
+        obtain_oauth_verifier = '/hackathon/tumblr'
+    context = {'title': 'API Examples Page', 'tumblr_url': obtain_oauth_verifier}
+    return render(request, 'hackathon/api_examples.html', context)
+
+def register(request):
+    registered = False
+    if request.method == 'POST':
+        user_form = UserForm(data=request.POST)
+        if user_form.is_valid():
+            user = user_form.save()
+            user.set_password(user.password)
+            user.save()
+            registered = True
+        else:
+            print user_form.errors
+    else:
+        user_form = UserForm()
+
+    
+    return render(request,
+            'hackathon/register.html',
+            {'user_form': user_form, 'registered': registered} )
+
+def user_login(request):
+
+    
+    if request.method == 'POST':
+        username = request.POST.get('username')
+        password = request.POST.get('password')
+
+
+        user = authenticate(username=username, password=password)
+
+
+        if user:
+            if user.is_active:
+                login(request, user)
+                return HttpResponseRedirect('/hackathon/')
+            else:
+                return HttpResponse("Your Django Hackathon account is disabled.")
+        else:
+            print "Invalid login details: {0}, {1}".format(username, password)
+            return HttpResponse("Invalid login details supplied.")
+
+    else:
+        return render(request, 'hackathon/login.html', {})
+
+def user_logout(request):
+    logout(request)
+    return HttpResponseRedirect('/hackathon/')
+
+def steam(request):
+    #Should link to test of Steam API example.
+    key = '231E98D442E52B87110816C3D5114A1D'
+    SteamUN = "Marorin"
+    steamID = steamIDPulling(SteamUN, key)
+    game = gamesPulling(steamID, key)
+    return render(request,'hackathon/steam.html', {"game": game })
+
+def github(request):
+    allData = {}
+    userData = getUserData(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    repositories = getUserRepositories(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    list = getTopContributedRepositories(repositories, settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    filtered = filterCommits(list)
+    stargazers = getStarGazerCount(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    filteredStargazers = filterStarGazerCount(stargazers)
+    forkedRepos = getForkedRepositories(settings.GITHUB_CLIENT_ID, settings.GITHUB_CLIENT_SECRET)
+    allData['userData'] = userData
+    allData['filteredData'] = filtered
+    allData['filteredStargazers'] = filteredStargazers
+    allData['forkedRepos'] = forkedRepos
+
+    return render(request, 'hackathon/github.html', { 'data': allData })
+
+def tumblr(request):
+    ''' Tumblr api calls '''
+    #retrieve verifier via url link
+    #if not request.GET.items():
+    #    return HttpResponseRedirect('/hackathon/api/')
+    if not getTumblr.accessed:
+        oauth_verifier = request.GET.get('oauth_verifier')
+        getTumblr.access_token_url(oauth_verifier)
+    #get blogger twitterthecomic's blog information
+    blog = getTumblr.getBlogInfo('twitterthecomic')
+    #get tags that was tagged along starbucks
+    tagged_blog = getTumblr.getTaggedInfo("starbucks")
+    #get blog information tagged with starbucks
+    blogontag = getTumblr.getTaggedBlog("starbucks")
+    #get user's information
+    userinfo, total_blog = getTumblr.getUserInfo()
+    context = {'title': "What's up Starbucks?", 'blogData': blog, 'blogTag': tagged_blog, 'blogontag': blogontag, 'userinfo': userinfo, 'total_blog':total_blog}
+    return render(request, 'hackathon/tumblr.html', context)
+
+def linkedin(request):
+    userinfo = getUserInfo()
+    context = {'title': 'linkedin Example','userdata': userinfo}
+    return render(request, 'hackathon/linkedin.html', context)
+
+class JSONResponse(HttpResponse):
+    """
+    An HttpResponse that renders its content into JSON.
+    """
+    def __init__(self, data, **kwargs):
+        content = JSONRenderer().render(data)
+        kwargs['content_type'] = 'application/json'
+        super(JSONResponse, self).__init__(content, **kwargs)
+
+@csrf_exempt
+def snippet_list(request):
+    """
+    List all code snippets, or create a new snippet.
+    """
+    if request.method == 'GET':
+        snippets = Snippet.objects.all()
+        serializer = SnippetSerializer(snippets, many=True)
+        return JSONResponse(serializer.data)
+

+ 0 - 0
hackathon_starter/hackathon_starter/__init__.py


+ 116 - 0
hackathon_starter/hackathon_starter/settings.py

@@ -0,0 +1,116 @@
+"""
+Django settings for hackathon_starter project.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.7/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.7/ref/settings/
+"""
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+import os
+BASE_DIR = os.path.dirname(os.path.dirname(__file__))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'keuhh=0*%do-ayvy*m2k=vss*$7)j8q!@u0+d^na7mi2(^!l!d'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+TEMPLATE_DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = (
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'hackathon',
+    'bootstrapform',
+    # 'django_openid',
+    'django_nose',
+    'rest_framework',
+    'corsheaders',
+)
+
+MIDDLEWARE_CLASSES = (
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'corsheaders.middleware.CorsMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    #'django_openid_consumer.SessionConsumer',
+)
+
+ROOT_URLCONF = 'hackathon_starter.urls'
+
+WSGI_APPLICATION = 'hackathon_starter.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    }
+}
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.7/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.7/howto/static-files/
+
+STATIC_URL = '/static/'
+
+TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
+
+# Use nose to run all tests
+TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
+
+# Tell nose to measure coverage on the 'foo' and 'bar' apps
+NOSE_ARGS = [
+    '--with-coverage',
+    '--cover-package=hackathon/scripts',
+]
+
+CORS_ORIGIN_ALLOW_ALL = True
+
+############
+#   KEYS   #
+############
+
+GITHUB_CLIENT_ID = 'client_id=2404a1e21aebd902f6db'
+GITHUB_CLIENT_SECRET = 'client_secret=3da44769d4b7c9465fa4c812669148a163607c23'
+TUMBLR_CONSUMER_KEY = 'KrSbAc9cYLmIgVAn1D21FjRR97QWsutNMxkPDFBxo8CMWtMk4M'
+TUMBLR_CONSUMER_SECRET ='lKWMtL2Lj8zr5pY51PVqT8ugeoG0DjrdgoFewM0QTSyJ12jP8d'
+TWITTER_TOKEN = 'F05dgLAzHEOalb4K2xDQ8Umm8'
+TWITTER_SECRET = 'Yy3a74Z7gvyhxRruJsvUtUl8uK8iv6qKkVqbZSijUxK71Z1qTY'
+

+ 8 - 0
hackathon_starter/hackathon_starter/urls.py

@@ -0,0 +1,8 @@
+from django.conf.urls import patterns, include, url
+from django.contrib import admin
+
+urlpatterns = patterns('',
+    url(r'^hackathon/', include('hackathon.urls')),
+    url(r'^admin/', include(admin.site.urls)),
+    # url(r'^openid/(.*)', SessionConsumer()),
+)

+ 14 - 0
hackathon_starter/hackathon_starter/wsgi.py

@@ -0,0 +1,14 @@
+"""
+WSGI config for hackathon_starter project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
+"""
+
+import os
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hackathon_starter.settings")
+
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()

+ 10 - 0
hackathon_starter/manage.py

@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hackathon_starter.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)

+ 3 - 0
ionic/.bowerrc

@@ -0,0 +1,3 @@
+{
+  "directory": "www/lib"
+}

+ 6 - 0
ionic/.gitignore

@@ -0,0 +1,6 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+node_modules/
+platforms/
+plugins/

+ 7 - 0
ionic/bower.json

@@ -0,0 +1,7 @@
+{
+  "name": "conference",
+  "private": "true",
+  "devDependencies": {
+    "ionic": "driftyco/ionic-bower#1.0.0-rc.2"
+  }
+}

+ 49 - 0
ionic/config.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<widget id="com.ionicframework.conference121422" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+  <name>conference</name>
+  <description>
+        An Ionic Framework and Cordova project.
+    </description>
+  <author email="hi@ionicframework" href="http://ionicframework.com/">
+      Ionic Framework Team
+    </author>
+  <content src="index.html"/>
+  <access origin="*"/>
+  <preference name="webviewbounce" value="false"/>
+  <preference name="UIWebViewBounce" value="false"/>
+  <preference name="DisallowOverscroll" value="true"/>
+  <preference name="BackupWebStorage" value="none"/>
+  <preference name="SplashScreen" value="screen"/>
+  <preference name="SplashScreenDelay" value="3000"/>
+  <feature name="StatusBar">
+    <param name="ios-package" value="CDVStatusBar" onload="true"/>
+  </feature>
+  <platform name="ios">
+    <icon src="resources/ios/icon/icon.png" width="57" height="57"/>
+    <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
+    <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
+    <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
+    <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
+    <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
+    <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
+    <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
+    <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
+    <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
+    <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
+    <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
+    <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
+    <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
+    <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
+    <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
+    <splash src="resources/ios/splash/Default-568h@2x~iphone.png" height="1136" width="640"/>
+    <splash src="resources/ios/splash/Default-667h.png" height="1334" width="750"/>
+    <splash src="resources/ios/splash/Default-736h.png" height="2208" width="1242"/>
+    <splash src="resources/ios/splash/Default-Landscape-736h.png" height="1242" width="2208"/>
+    <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" height="1536" width="2048"/>
+    <splash src="resources/ios/splash/Default-Landscape~ipad.png" height="768" width="1024"/>
+    <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" height="2048" width="1536"/>
+    <splash src="resources/ios/splash/Default-Portrait~ipad.png" height="1024" width="768"/>
+    <splash src="resources/ios/splash/Default@2x~iphone.png" height="960" width="640"/>
+    <splash src="resources/ios/splash/Default~iphone.png" height="480" width="320"/>
+  </platform>
+</widget>

+ 50 - 0
ionic/gulpfile.js

@@ -0,0 +1,50 @@
+var gulp = require('gulp');
+var gutil = require('gulp-util');
+var bower = require('bower');
+var concat = require('gulp-concat');
+var sass = require('gulp-sass');
+var minifyCss = require('gulp-minify-css');
+var rename = require('gulp-rename');
+var sh = require('shelljs');
+
+var paths = {
+  sass: ['./scss/**/*.scss']
+};
+
+gulp.task('default', ['sass']);
+
+gulp.task('sass', function(done) {
+  gulp.src('./scss/ionic.app.scss')
+    .pipe(sass())
+    .pipe(gulp.dest('./www/css/'))
+    .pipe(minifyCss({
+      keepSpecialComments: 0
+    }))
+    .pipe(rename({ extname: '.min.css' }))
+    .pipe(gulp.dest('./www/css/'))
+    .on('end', done);
+});
+
+gulp.task('watch', function() {
+  gulp.watch(paths.sass, ['sass']);
+});
+
+gulp.task('install', ['git-check'], function() {
+  return bower.commands.install()
+    .on('log', function(data) {
+      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
+    });
+});
+
+gulp.task('git-check', function(done) {
+  if (!sh.which('git')) {
+    console.log(
+      '  ' + gutil.colors.red('Git is not installed.'),
+      '\n  Git, the version control system, is required to download Ionic.',
+      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
+      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
+    );
+    process.exit(1);
+  }
+  done();
+});

+ 83 - 0
ionic/hooks/README.md

@@ -0,0 +1,83 @@
+<!--
+#
+# 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.
+#
+-->
+# Cordova Hooks
+
+This directory may contain scripts used to customize cordova commands. This
+directory used to exist at `.cordova/hooks`, but has now been moved to the
+project root. Any scripts you add to these directories will be executed before
+and after the commands corresponding to the directory name. Useful for
+integrating your own build systems or integrating with version control systems.
+
+__Remember__: Make your scripts executable.
+
+## Hook Directories
+The following subdirectories will be used for hooks:
+
+    after_build/
+    after_compile/
+    after_docs/
+    after_emulate/
+    after_platform_add/
+    after_platform_rm/
+    after_platform_ls/
+    after_plugin_add/
+    after_plugin_ls/
+    after_plugin_rm/
+    after_plugin_search/
+    after_prepare/
+    after_run/
+    after_serve/
+    before_build/
+    before_compile/
+    before_docs/
+    before_emulate/
+    before_platform_add/
+    before_platform_rm/
+    before_platform_ls/
+    before_plugin_add/
+    before_plugin_ls/
+    before_plugin_rm/
+    before_plugin_search/
+    before_prepare/
+    before_run/
+    before_serve/
+    pre_package/ <-- Windows 8 and Windows Phone only.
+
+## Script Interface
+
+All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
+
+* CORDOVA_VERSION - The version of the Cordova-CLI.
+* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
+* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
+* CORDOVA_HOOK - Path to the hook that is being executed.
+* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
+
+If a script returns a non-zero exit code, then the parent cordova command will be aborted.
+
+
+## Writing hooks
+
+We highly recommend writting your hooks using Node.js so that they are
+cross-platform. Some good examples are shown here:
+
+[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
+

+ 94 - 0
ionic/hooks/after_prepare/010_add_platform_class.js

@@ -0,0 +1,94 @@
+#!/usr/bin/env node
+
+// Add Platform Class
+// v1.0
+// Automatically adds the platform class to the body tag
+// after the `prepare` command. By placing the platform CSS classes
+// directly in the HTML built for the platform, it speeds up
+// rendering the correct layout/style for the specific platform
+// instead of waiting for the JS to figure out the correct classes.
+
+var fs = require('fs');
+var path = require('path');
+
+var rootdir = process.argv[2];
+
+function addPlatformBodyTag(indexPath, platform) {
+  // add the platform class to the body tag
+  try {
+    var platformClass = 'platform-' + platform;
+    var cordovaClass = 'platform-cordova platform-webview';
+
+    var html = fs.readFileSync(indexPath, 'utf8');
+
+    var bodyTag = findBodyTag(html);
+    if(!bodyTag) return; // no opening body tag, something's wrong
+
+    if(bodyTag.indexOf(platformClass) > -1) return; // already added
+
+    var newBodyTag = bodyTag;
+
+    var classAttr = findClassAttr(bodyTag);
+    if(classAttr) {
+      // body tag has existing class attribute, add the classname
+      var endingQuote = classAttr.substring(classAttr.length-1);
+      var newClassAttr = classAttr.substring(0, classAttr.length-1);
+      newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
+      newBodyTag = bodyTag.replace(classAttr, newClassAttr);
+
+    } else {
+      // add class attribute to the body tag
+      newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
+    }
+
+    html = html.replace(bodyTag, newBodyTag);
+
+    fs.writeFileSync(indexPath, html, 'utf8');
+
+    process.stdout.write('add to body class: ' + platformClass + '\n');
+  } catch(e) {
+    process.stdout.write(e);
+  }
+}
+
+function findBodyTag(html) {
+  // get the body tag
+  try{
+    return html.match(/<body(?=[\s>])(.*?)>/gi)[0];
+  }catch(e){}
+}
+
+function findClassAttr(bodyTag) {
+  // get the body tag's class attribute
+  try{
+    return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
+  }catch(e){}
+}
+
+if (rootdir) {
+
+  // go through each of the platform directories that have been prepared
+  var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
+
+  for(var x=0; x<platforms.length; x++) {
+    // open up the index.html file at the www root
+    try {
+      var platform = platforms[x].trim().toLowerCase();
+      var indexPath;
+
+      if(platform == 'android') {
+        indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');
+      } else {
+        indexPath = path.join('platforms', platform, 'www', 'index.html');
+      }
+
+      if(fs.existsSync(indexPath)) {
+        addPlatformBodyTag(indexPath, platform);
+      }
+
+    } catch(e) {
+      process.stdout.write(e);
+    }
+  }
+
+}

+ 4 - 0
ionic/ionic.project

@@ -0,0 +1,4 @@
+{
+  "name": "conference",
+  "app_id": ""
+}

+ 25 - 0
ionic/package.json

@@ -0,0 +1,25 @@
+{
+  "name": "conference",
+  "version": "1.0.0",
+  "description": "conference: An Ionic project",
+  "dependencies": {
+    "gulp": "^3.5.6",
+    "gulp-sass": "^1.3.3",
+    "gulp-concat": "^2.2.0",
+    "gulp-minify-css": "^0.3.0",
+    "gulp-rename": "^1.2.0"
+  },
+  "devDependencies": {
+    "bower": "^1.3.3",
+    "gulp-util": "^2.2.14",
+    "shelljs": "^0.3.0"
+  },
+  "cordovaPlugins": [
+    "org.apache.cordova.device",
+    "org.apache.cordova.console",
+    "com.ionic.keyboard"
+  ],
+  "cordovaPlatforms": [
+    "ios"
+  ]
+}

+ 202 - 0
ionic/plugins/com.ionic.keyboard/LICENSE

@@ -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 2014 Drifty Co.
+
+   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.

+ 123 - 0
ionic/plugins/com.ionic.keyboard/README.md

@@ -0,0 +1,123 @@
+Keyboard
+======
+
+The `cordova.plugins.Keyboard` object provides functions to make interacting with the keyboard easier, and fires events to indicate that the keyboard will hide/show.
+
+    cordova plugin add com.ionic.keyboard
+
+Methods
+-------
+
+- cordova.plugins.Keyboard.hideKeyboardAccessoryBar
+- cordova.plugins.Keyboard.close
+- cordova.plugins.Keyboard.disableScroll
+- cordova.plugins.Keyboard.show
+
+Properties
+--------
+
+- cordova.plugins.Keyboard.isVisible
+
+Events
+--------
+
+These events are fired on the window.
+
+- native.keyboardshow
+  * A number `keyboardHeight` is given on the event object, which is the pixel height of the keyboard.
+- native.keyboardhide
+
+Keyboard.hideKeyboardAccessoryBar
+=================
+
+Hide the keyboard accessory bar with the next, previous and done buttons.
+
+    cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
+    cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false);
+
+Supported Platforms
+-------------------
+
+- iOS
+
+
+Keyboard.close
+=================
+
+Close the keyboard if it is open.
+
+    cordova.plugins.Keyboard.close();
+
+Supported Platforms
+-------------------
+
+- iOS, Android, Blackberry 10
+
+
+Keyboard.disableScroll
+=================
+
+Disable native scrolling, useful if you are using JavaScript to scroll
+
+    cordova.plugins.Keyboard.disableScroll(true);
+    cordova.plugins.Keyboard.disableScroll(false);
+
+Supported Platforms
+-------------------
+
+- iOS
+
+Keyboard.show
+=================
+
+Force keyboard to be shown on Android. This typically helps if autofocus on a text element does not pop up the keyboard automatically
+
+    cordova.plugins.Keyboard.show();
+
+Supported Platforms
+
+- Android, Blackberry 10
+
+native.keyboardshow
+=================
+
+This event fires when the keyboard will be shown
+
+    window.addEventListener('native.keyboardshow', keyboardShowHandler);
+
+    function keyboardShowHandler(e){
+        alert('Keyboard height is: ' + e.keyboardHeight);
+    }
+
+Properties
+-----------
+
+keyboardHeight: the height of the keyboard in pixels
+
+
+Supported Platforms
+-------------------
+
+- iOS, Android, Blackberry 10
+
+
+native.keyboardhide
+=================
+
+This event fires when the keyboard will hide
+
+    window.addEventListener('native.keyboardhide', keyboardHideHandler);
+
+    function keyboardHideHandler(e){
+        alert('Goodnight, sweet prince');
+    }
+
+Properties
+-----------
+
+None
+
+Supported Platforms
+-------------------
+
+- iOS, Android, Blackberry 10

+ 19 - 0
ionic/plugins/com.ionic.keyboard/package.json

@@ -0,0 +1,19 @@
+{
+    "version": "1.0.4",
+    "name": "com.ionic.keyboard",
+    "cordova_name": "Keyboard",
+    "description": "Ionic Keyboard Plugin",
+    "license": "Apache 2.0",
+    "repo": "https://github.com/driftyco/ionic-plugins-keyboard.git",
+    "issue": "https://github.com/driftyco/ionic-plugins-keyboard/issues",
+    "keywords": [
+        "Ionic",
+        "keyboard"
+    ],
+    "platforms": [
+        "android",
+        "ios",
+        "blackberry10"
+    ],
+    "engines": []
+}

+ 55 - 0
ionic/plugins/com.ionic.keyboard/plugin.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    id="com.ionic.keyboard"
+    version="1.0.4">
+    <name>Keyboard</name>
+    <description>Ionic Keyboard Plugin</description>
+    <license>Apache 2.0</license>
+    <keywords>Ionic,keyboard</keywords>
+    <repo>https://github.com/driftyco/ionic-plugins-keyboard.git</repo>
+    <issue>https://github.com/driftyco/ionic-plugins-keyboard/issues</issue>
+
+  <js-module src="www/keyboard.js" name="keyboard">
+    <clobbers target="cordova.plugins.Keyboard" />
+  </js-module>
+
+  <!-- android -->
+  <platform name="android">
+
+    <config-file target="res/xml/config.xml" parent="/*">
+      <feature name="Keyboard">
+        <param name="android-package" value="com.ionic.keyboard.IonicKeyboard" />
+        <param name="onload" value="true" />
+      </feature>
+    </config-file>
+
+    <source-file src="src/android/IonicKeyboard.java" target-dir="src/com/ionic/keyboard" />
+  </platform>
+
+    <!-- ios -->
+    <platform name="ios">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Keyboard">
+                <param name="ios-package" value="IonicKeyboard" onload="true" />
+            </feature>
+        </config-file>
+
+        <header-file src="src/ios/IonicKeyboard.h" />
+        <source-file src="src/ios/IonicKeyboard.m" />
+        <header-file src="src/ios/UIWebViewExtension.h" />
+        <source-file src="src/ios/UIWebViewExtension.m" />
+    </platform>
+
+    <!-- blackberry10 -->
+    <platform name="blackberry10">
+        <source-file src="src/blackberry10/index.js" target-dir='Keyboard' />
+        <lib-file src="src/blackberry10/native/device/libKeyboard.so" arch="device"/>
+        <lib-file src="src/blackberry10/native/simulator/libKeyboard.so" arch="simulator"/>
+        <config-file target="www/config.xml" parent="/widget">
+               <feature name="Keyboard" value="com.ionic.keyboard"/>
+            
+        </config-file>
+    </platform>
+
+</plugin>

+ 96 - 0
ionic/plugins/com.ionic.keyboard/src/android/IonicKeyboard.java

@@ -0,0 +1,96 @@
+package com.ionic.keyboard;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginResult.Status;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.inputmethod.InputMethodManager;
+
+public class IonicKeyboard extends CordovaPlugin{
+
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        super.initialize(cordova, webView);
+
+        //calculate density-independent pixels (dp)
+        //http://developer.android.com/guide/practices/screens_support.html
+        DisplayMetrics dm = new DisplayMetrics();
+        cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
+        final float density = dm.density;
+
+        final CordovaWebView appView = webView;
+
+        //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing
+        final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView();
+        OnGlobalLayoutListener list = new OnGlobalLayoutListener() {
+            int previousHeightDiff = 0;
+            @Override
+            public void onGlobalLayout() {
+                Rect r = new Rect();
+                //r will be populated with the coordinates of your view that area still visible.
+                rootView.getWindowVisibleDisplayFrame(r);
+
+                int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
+                int pixelHeightDiff = (int)(heightDiff / density);
+                if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard...
+                    appView.sendJavascript("cordova.plugins.Keyboard.isVisible = true");
+                    appView.sendJavascript("cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});");
+
+                    //deprecated
+                    appView.sendJavascript("cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});");
+                }
+                else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){
+                    appView.sendJavascript("cordova.plugins.Keyboard.isVisible = false");
+                    appView.sendJavascript("cordova.fireWindowEvent('native.keyboardhide')");
+
+                    //deprecated
+                    appView.sendJavascript("cordova.fireWindowEvent('native.hidekeyboard')");
+                }
+                previousHeightDiff = pixelHeightDiff;
+             }
+        };
+
+        rootView.getViewTreeObserver().addOnGlobalLayoutListener(list);
+    }
+
+    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
+        if ("close".equals(action)) {
+            cordova.getThreadPool().execute(new Runnable() {
+                public void run() {
+                    //http://stackoverflow.com/a/7696791/1091751
+                    InputMethodManager inputManager = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+                    View v = cordova.getActivity().getCurrentFocus();
+
+                    if (v == null) {
+                        callbackContext.error("No current focus");
+                    } else {
+                        inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+                        callbackContext.success(); // Thread-safe.
+                    }
+                }
+            });
+            return true;
+        }
+        if ("show".equals(action)) {
+            cordova.getThreadPool().execute(new Runnable() {
+                public void run() {
+                    ((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
+                    callbackContext.success(); // Thread-safe.
+                }
+            });
+            return true;
+        }
+        return false;  // Returning false results in a "MethodNotFound" error.
+    }
+
+
+}
+

+ 135 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/index.js

@@ -0,0 +1,135 @@
+
+
+var keyboard,
+	resultObjs = {},
+	threadCallback = null,
+   _utils = require("../../lib/utils");
+   _event = require("../../lib/event");
+    _webview = require("../../lib/webview");
+
+
+
+
+module.exports = {
+
+	// Code can be declared and used outside the module.exports object,
+	// but any functions to be called by client.js need to be declared
+	// here in this object.
+
+	// These methods call into JNEXT.Keyboard which handles the
+	// communication through the JNEXT plugin to keyboard_js.cpp
+	startService: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+		
+	result.ok(keyboard.getInstance().startService(), false);
+	},
+	show: function (success, fail, args, env) {
+		var result = new PluginResult(args, env);
+		
+		result.ok(keyboard.getInstance().showKeyboard(), false);
+	},
+	close: function (success, fail, args, env) {
+	var result = new PluginResult(args, env);
+		
+	result.ok(keyboard.getInstance().closeKeyboard(), false);
+	}
+};
+
+keyboardShow = function(a){
+	_webview.executeJavascript("cordova.plugins.Keyboard.isVisible = true");
+	_webview.executeJavascript("cordova.fireDocumentEvent('native.keyboardshow',"+a+")");
+	 
+}
+keyboardHide = function(){
+	_webview.executeJavascript("cordova.plugins.Keyboard.isVisible = false");
+	_webview.executeJavascript("cordova.fireDocumentEvent('native.keyboardhide','')");
+	
+}
+onStart = function() {
+		_webview.executeJavascript("cordova.exec("+null+", "+null+", 'Keyboard', 'startService', '')");
+	}
+
+setTimeout(onStart,2000);
+
+///////////////////////////////////////////////////////////////////
+// JavaScript wrapper for JNEXT plugin for connection
+///////////////////////////////////////////////////////////////////
+
+JNEXT.Keyboard = function () {
+	var self = this,
+		hasInstance = false;
+
+	self.getId = function () {
+		return self.m_id;
+	};
+
+	self.init = function () {
+		if (!JNEXT.require("libKeyboard")) {
+			return false;
+		}
+
+		self.m_id = JNEXT.createObject("libKeyboard.Keyboard_JS");
+
+		if (self.m_id === "") {
+			return false;
+		}
+
+		JNEXT.registerEvents(self);
+	};
+
+	// ************************
+	// Enter your methods here
+	// ************************
+
+	// calls into InvokeMethod(string command) in keyboard_js.cpp
+	self.startService = function () {
+		return JNEXT.invoke(self.m_id, "startService");
+	};
+	self.showKeyboard = function () {
+		return JNEXT.invoke(self.m_id, "showKeyboard");
+	};
+	self.closeKeyboard = function () {
+		return JNEXT.invoke(self.m_id, "closeKeyboard");
+	};
+
+	self.onEvent = function (strData) 	{ 	// Fired by the Event framework (used by asynchronous callbacks)
+		var arData = strData.split(" "),
+        strEventDesc = arData[0],
+        jsonData;
+
+	if (strEventDesc === "native.keyboardshow") {
+		    	jsonData = arData.slice(1, arData.length).join(" ");
+		    	keyboardShow(jsonData);
+		    	
+    }
+    else if (strEventDesc === "native.keyboardhide") {		 
+		    	keyboardHide();
+    }
+
+	};
+
+	// Thread methods
+	self.keyboardStartThread = function (callbackId) {
+		return JNEXT.invoke(self.m_id, "keyboardStartThread " + callbackId);
+	};
+	self.keyboardStopThread = function () {
+		return JNEXT.invoke(self.m_id, "keyboardStopThread");
+	};
+
+	// ************************
+	// End of methods to edit
+	// ************************
+	self.m_id = "";
+
+	self.getInstance = function () {
+		if (!hasInstance) {
+			hasInstance = true;
+			self.init();
+		}
+		return self;
+	};
+
+};
+
+keyboard = new JNEXT.Keyboard();
+

+ 222 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/.cproject

@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" moduleId="org.eclipse.cdt.core.settings" name="device">
+				<externalSettings>
+					<externalSetting>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/Cordova-Keyboard"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/Cordova-Keyboard/device"/>
+						<entry flags="RESOLVED" kind="libraryFile" name="Cordova-Keyboard" srcPrefixMapping="" srcRootPath=""/>
+					</externalSetting>
+				</externalSettings>
+				<extensions>
+					<extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" name="device" parent="com.qnx.qcc.configuration.sharedLib.release">
+					<folderInfo id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567." name="/" resourcePath="">
+						<toolChain id="com.qnx.qcc.toolChain.2215983" name="QNX QCC" superClass="com.qnx.qcc.toolChain">
+							<option id="com.qnx.qcc.option.cpu.315540759" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/>
+							<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1359109141" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+							<builder buildPath="${workspace_loc:/Keyboard/Device-Release}" id="com.qnx.nto.938326560" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/>
+							<tool id="com.qnx.qcc.tool.compiler.242697771" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+								<option id="com.qnx.qcc.option.compiler.shared.553244928" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.optlevel.2070537906" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.2" valueType="enumerated"/>
+								<option id="com.qnx.qcc.option.compiler.includePath.1483355415" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/bb"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4/QtCore"/>
+									<listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.security.9625963" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.defines.872099896" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.qccoptions.1015003128" name="QCC Options" superClass="com.qnx.qcc.option.compiler.qccoptions" valueType="stringList">
+									<listOptionValue builtIn="false" value="-frecord-gcc-switches"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.compiler.1443568066" superClass="com.qnx.qcc.inputType.compiler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.assembler.1996828008" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+								<inputType id="com.qnx.qcc.inputType.assembler.116798417" superClass="com.qnx.qcc.inputType.assembler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.linker.871546588" name="QCC Linker" superClass="com.qnx.qcc.tool.linker">
+								<option id="com.qnx.qcc.option.linker.shared.915102752" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraryPaths.1049529253" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib/qt4/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/>
+								</option>
+								<option id="com.qnx.qcc.option.linker.security.1157664997" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraries.1316432206" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
+									<listOptionValue builtIn="false" value="slog2"/>
+									<listOptionValue builtIn="false" value="QtCore"/>
+									<listOptionValue builtIn="false" value="bb"/>
+									<listOptionValue builtIn="false" value="bps"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.linker.1028572887" superClass="com.qnx.qcc.inputType.linker">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="com.qnx.qcc.tool.archiver.1781914947" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+		<cconfiguration id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" moduleId="org.eclipse.cdt.core.settings" name="simulator">
+				<externalSettings>
+					<externalSetting>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/Cordova-Keyboard"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/Cordova-Keyboard/simulator"/>
+						<entry flags="RESOLVED" kind="libraryFile" name="Cordova-Keyboard" srcPrefixMapping="" srcRootPath=""/>
+					</externalSetting>
+				</externalSettings>
+				<extensions>
+					<extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" name="simulator" parent="com.qnx.qcc.configuration.sharedLib.debug">
+					<folderInfo id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091." name="/" resourcePath="">
+						<toolChain id="com.qnx.qcc.toolChain.688026907" name="QNX QCC" superClass="com.qnx.qcc.toolChain">
+							<targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.469207190" osList="all" superClass="com.qnx.qcc.targetPlatform"/>
+							<builder buildPath="${workspace_loc:/Keyboard/Simulator-Debug}" id="com.qnx.nto.2029800497" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/>
+							<tool id="com.qnx.qcc.tool.compiler.1028279123" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
+								<option id="com.qnx.qcc.option.compiler.shared.235893159" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.optlevel.1164238904" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/>
+								<option id="com.qnx.qcc.option.compile.debug.3716470" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.includePath.306305432" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/bb"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4/QtCore"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4"/>
+									<listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/>
+								</option>
+								<option id="com.qnx.qcc.option.compiler.security.1730007887" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.defines.1526896965" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
+									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.compiler.1881183122" superClass="com.qnx.qcc.inputType.compiler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.assembler.312168125" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
+								<option id="com.qnx.qcc.option.assembler.debug.416544277" name="Debug (-g)" superClass="com.qnx.qcc.option.assembler.debug" value="true" valueType="boolean"/>
+								<inputType id="com.qnx.qcc.inputType.assembler.1722778407" superClass="com.qnx.qcc.inputType.assembler"/>
+							</tool>
+							<tool id="com.qnx.qcc.tool.linker.2130364088" name="QCC Linker" superClass="com.qnx.qcc.tool.linker">
+								<option id="com.qnx.qcc.option.linker.debug.1332880614" name="Debug (-g)" superClass="com.qnx.qcc.option.linker.debug" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.shared.1633267255" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraryPaths.565794953" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths">
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib/qt4/lib"/>
+									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/>
+								</option>
+								<option id="com.qnx.qcc.option.linker.security.9141791" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.linker.libraries.220836649" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
+									<listOptionValue builtIn="false" value="slog2"/>
+									<listOptionValue builtIn="false" value="QtCore"/>
+									<listOptionValue builtIn="false" value="bb"/>
+									<listOptionValue builtIn="false" value="bps"/>
+								</option>
+								<inputType id="com.qnx.qcc.inputType.linker.167117375" superClass="com.qnx.qcc.inputType.linker">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="com.qnx.qcc.tool.archiver.489682882" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="Keyboard.null.138005006" name="Keyboard"/>
+	</storageModule>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Simulator-Profile">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="simulator">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Simulator-Coverage">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Device-Profile">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Device-Debug">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Simulator-Debug">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="device">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Device-Release">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+		<configuration configurationName="Device-Coverage">
+			<resource resourceType="PROJECT" workspacePath="/Keyboard"/>
+		</configuration>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.941124085">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.1806890017">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.608922875">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.27502649">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.193597202">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.537092296">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.1877214659">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+</cproject>

+ 76 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/.project

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Keyboard</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+				<dictionary>
+					<key>?name?</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildArguments</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildCommand</key>
+					<value>make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.buildLocation</key>
+					<value>${workspace_loc:/Keyboard/Device-Release}</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.contents</key>
+					<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>true</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+		<nature>com.qnx.tools.ide.bbt.core.bbtnature</nature>
+	</natures>
+</projectDescription>

binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/libKeyboard.so


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_reader.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_value.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/json_writer.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/plugin.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/public/tokenizer.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/CallKeyboard.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/Logger.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/keyboard_js.o


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/device/src/keyboard_ndk.o


+ 19 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/autolink.h

@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK)  &&  !defined(JSON_DLL_BUILD)  &&  !defined(JSON_IN_CPPTL)
+#  define CPPTL_AUTOLINK_NAME "json"
+#  undef CPPTL_AUTOLINK_DLL
+#  ifdef JSON_DLL
+#   define CPPTL_AUTOLINK_DLL
+#  endif
+#  include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED

+ 43 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/config.h

@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL!
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED

+ 42 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/features.h

@@ -0,0 +1,42 @@
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+# include "forwards.h"
+
+namespace Json {
+
+   /** \brief Configuration passed to reader and writer.
+    * This configuration object can be used to force the Reader or Writer
+    * to behave in a standard conforming way.
+    */
+   class JSON_API Features
+   {
+   public:
+      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+       * - C & C++ comments are allowed
+       * - Root object can be any JSON value
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features all();
+
+      /** \brief A configuration that is strictly compatible with the JSON specification.
+       * - Comments are forbidden.
+       * - Root object must be either an array or an object value.
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features strictMode();
+
+      /** \brief Initialize the configuration like JsonConfig::allFeatures;
+       */
+      Features();
+
+      /// \c true if comments are allowed. Default: \c true.
+      bool allowComments_;
+
+      /// \c true if root must be either an array or an object value. Default: \c false.
+      bool strictRoot_;
+   };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED

+ 39 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/forwards.h

@@ -0,0 +1,39 @@
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+# include "config.h"
+
+namespace Json {
+
+   // writer.h
+   class FastWriter;
+   class StyledWriter;
+
+   // reader.h
+   class Reader;
+
+   // features.h
+   class Features;
+
+   // value.h
+   typedef int Int;
+   typedef unsigned int UInt;
+   class StaticString;
+   class Path;
+   class PathArgument;
+   class Value;
+   class ValueIteratorBase;
+   class ValueIterator;
+   class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   class ValueAllocator;
+   class ValueMapAllocator;
+   class ValueInternalLink;
+   class ValueInternalArray;
+   class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED

+ 10 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/json.h

@@ -0,0 +1,10 @@
+#ifndef JSON_JSON_H_INCLUDED
+# define JSON_JSON_H_INCLUDED
+
+# include "autolink.h"
+# include "value.h"
+# include "reader.h"
+# include "writer.h"
+# include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED

+ 196 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/reader.h

@@ -0,0 +1,196 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+    *
+    */
+   class JSON_API Reader
+   {
+   public:
+      typedef char Char;
+      typedef const Char *Location;
+
+      /** \brief Constructs a Reader allowing all features
+       * for parsing.
+       */
+      Reader();
+
+      /** \brief Constructs a Reader allowing the specified feature set
+       * for parsing.
+       */
+      Reader( const Features &features );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const std::string &document, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const char *beginDoc, const char *endDoc, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /// \brief Parse from input stream.
+      /// \see Json::operator>>(std::istream&, Json::Value&).
+      bool parse( std::istream &is,
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       */
+      std::string getFormatedErrorMessages() const;
+
+   private:
+      enum TokenType
+      {
+         tokenEndOfStream = 0,
+         tokenObjectBegin,
+         tokenObjectEnd,
+         tokenArrayBegin,
+         tokenArrayEnd,
+         tokenString,
+         tokenNumber,
+         tokenTrue,
+         tokenFalse,
+         tokenNull,
+         tokenArraySeparator,
+         tokenMemberSeparator,
+         tokenComment,
+         tokenError
+      };
+
+      class Token
+      {
+      public:
+         TokenType type_;
+         Location start_;
+         Location end_;
+      };
+
+      class ErrorInfo
+      {
+      public:
+         Token token_;
+         std::string message_;
+         Location extra_;
+      };
+
+      typedef std::deque<ErrorInfo> Errors;
+
+      bool expectToken( TokenType type, Token &token, const char *message );
+      bool readToken( Token &token );
+      void skipSpaces();
+      bool match( Location pattern, 
+                  int patternLength );
+      bool readComment();
+      bool readCStyleComment();
+      bool readCppStyleComment();
+      bool readString();
+      void readNumber();
+      bool readValue();
+      bool readObject( Token &token );
+      bool readArray( Token &token );
+      bool decodeNumber( Token &token );
+      bool decodeString( Token &token );
+      bool decodeString( Token &token, std::string &decoded );
+      bool decodeDouble( Token &token );
+      bool decodeUnicodeCodePoint( Token &token, 
+                                   Location &current, 
+                                   Location end, 
+                                   unsigned int &unicode );
+      bool decodeUnicodeEscapeSequence( Token &token, 
+                                        Location &current, 
+                                        Location end, 
+                                        unsigned int &unicode );
+      bool addError( const std::string &message, 
+                     Token &token,
+                     Location extra = 0 );
+      bool recoverFromError( TokenType skipUntilToken );
+      bool addErrorAndRecover( const std::string &message, 
+                               Token &token,
+                               TokenType skipUntilToken );
+      void skipUntilSpace();
+      Value &currentValue();
+      Char getNextChar();
+      void getLocationLineAndColumn( Location location,
+                                     int &line,
+                                     int &column ) const;
+      std::string getLocationLineAndColumn( Location location ) const;
+      void addComment( Location begin, 
+                       Location end, 
+                       CommentPlacement placement );
+      void skipCommentTokens( Token &token );
+   
+      typedef std::stack<Value *> Nodes;
+      Nodes nodes_;
+      Errors errors_;
+      std::string document_;
+      Location begin_;
+      Location end_;
+      Location current_;
+      Location lastValueEnd_;
+      Value *lastValue_;
+      std::string commentsBefore_;
+      Features features_;
+      bool collectComments_;
+   };
+
+   /** \brief Read from 'sin' into 'root'.
+
+    Always keep comments from the input JSON.
+
+    This can be used to read a file into a particular sub-object.
+    For example:
+    \code
+    Json::Value root;
+    cin >> root["dir"]["file"];
+    cout << root;
+    \endcode
+    Result:
+    \verbatim
+    {
+	"dir": {
+	    "file": {
+		// The input stream JSON would be nested here.
+	    }
+	}
+    }
+    \endverbatim
+    \throw std::exception on parse error.
+    \see Json::operator<<()
+   */
+   std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1069 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/value.h


+ 174 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json/writer.h

@@ -0,0 +1,174 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   class Value;
+
+   /** \brief Abstract class for writers.
+    */
+   class JSON_API Writer
+   {
+   public:
+      virtual ~Writer();
+
+      virtual std::string write( const Value &root ) = 0;
+   };
+
+   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+    *
+    * The JSON document is written in a single line. It is not intended for 'human' consumption,
+    * but may be usefull to support feature such as RPC where bandwith is limited.
+    * \sa Reader, Value
+    */
+   class JSON_API FastWriter : public Writer
+   {
+   public:
+      FastWriter();
+      virtual ~FastWriter(){}
+
+      void enableYAMLCompatibility();
+
+   public: // overridden from Writer
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+
+      std::string document_;
+      bool yamlCompatiblityEnabled_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledWriter: public Writer
+   {
+   public:
+      StyledWriter();
+      virtual ~StyledWriter(){}
+
+   public: // overridden from Writer
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param root Value to serialize.
+       * \return String containing the JSON document that represents the root value.
+       */
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::string document_;
+      std::string indentString_;
+      int rightMargin_;
+      int indentSize_;
+      bool addChildValues_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+        to a stream rather than to a string.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \param indentation Each level will be indented by this amount extra.
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledStreamWriter
+   {
+   public:
+      StyledStreamWriter( std::string indentation="\t" );
+      ~StyledStreamWriter(){}
+
+   public:
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param out Stream to write to. (Can be ostringstream, e.g.)
+       * \param root Value to serialize.
+       * \note There is no point in deriving from Writer, since write() should not return a value.
+       */
+      void write( std::ostream &out, const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::ostream* document_;
+      std::string indentString_;
+      int rightMargin_;
+      std::string indentation_;
+      bool addChildValues_;
+   };
+
+   std::string JSON_API valueToString( Int value );
+   std::string JSON_API valueToString( UInt value );
+   std::string JSON_API valueToString( double value );
+   std::string JSON_API valueToString( bool value );
+   std::string JSON_API valueToQuotedString( const char *value );
+
+   /// \brief Output using the StyledStreamWriter.
+   /// \see Json::operator>>()
+   std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED

+ 125 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_batchallocator.h

@@ -0,0 +1,125 @@
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ * 
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+        ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+   typedef AllocatedType Type;
+
+   BatchAllocator( unsigned int objectsPerPage = 255 )
+      : freeHead_( 0 )
+      , objectsPerPage_( objectsPerPage )
+   {
+//      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+      assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+      assert( objectsPerPage >= 16 );
+      batches_ = allocateBatch( 0 );   // allocated a dummy page
+      currentBatch_ = batches_;
+   }
+
+   ~BatchAllocator()
+   {
+      for ( BatchInfo *batch = batches_; batch;  )
+      {
+         BatchInfo *nextBatch = batch->next_;
+         free( batch );
+         batch = nextBatch;
+      }
+   }
+
+   /// allocate space for an array of objectPerAllocation object.
+   /// @warning it is the responsability of the caller to call objects constructors.
+   AllocatedType *allocate()
+   {
+      if ( freeHead_ ) // returns node from free list.
+      {
+         AllocatedType *object = freeHead_;
+         freeHead_ = *(AllocatedType **)object;
+         return object;
+      }
+      if ( currentBatch_->used_ == currentBatch_->end_ )
+      {
+         currentBatch_ = currentBatch_->next_;
+         while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
+            currentBatch_ = currentBatch_->next_;
+
+         if ( !currentBatch_  ) // no free batch found, allocate a new one
+         { 
+            currentBatch_ = allocateBatch( objectsPerPage_ );
+            currentBatch_->next_ = batches_; // insert at the head of the list
+            batches_ = currentBatch_;
+         }
+      }
+      AllocatedType *allocated = currentBatch_->used_;
+      currentBatch_->used_ += objectPerAllocation;
+      return allocated;
+   }
+
+   /// Release the object.
+   /// @warning it is the responsability of the caller to actually destruct the object.
+   void release( AllocatedType *object )
+   {
+      assert( object != 0 );
+      *(AllocatedType **)object = freeHead_;
+      freeHead_ = object;
+   }
+
+private:
+   struct BatchInfo
+   {
+      BatchInfo *next_;
+      AllocatedType *used_;
+      AllocatedType *end_;
+      AllocatedType buffer_[objectPerAllocation];
+   };
+
+   // disabled copy constructor and assignement operator.
+   BatchAllocator( const BatchAllocator & );
+   void operator =( const BatchAllocator &);
+
+   static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+   {
+      const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+                                + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+      BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+      batch->next_ = 0;
+      batch->used_ = batch->buffer_;
+      batch->end_ = batch->buffer_ + objectsPerPage;
+      return batch;
+   }
+
+   BatchInfo *batches_;
+   BatchInfo *currentBatch_;
+   /// Head of a single linked list within the allocated space of freeed object
+   AllocatedType *freeHead_;
+   unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+

+ 448 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_internalarray.inl

@@ -0,0 +1,448 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray(); // placement new
+      return array;
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      ValueInternalArray *array = arraysAllocator_.allocate();
+      new (array) ValueInternalArray( other ); // placement new
+      return array;
+   }
+
+   virtual void destructArray( ValueInternalArray *array )
+   {
+      if ( array )
+      {
+         array->~ValueInternalArray();
+         arraysAllocator_.release( array );
+      }
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( pagesAllocator_.allocate() );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         pagesAllocator_.release( value );
+   }
+private:
+   BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+   BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+   static DefaultValueArrayAllocator defaultAllocator;
+   static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+   return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+   DummyArrayAllocatorInitializer() 
+   {
+      arrayAllocator();      // ensure arrayAllocator() statics are initialized before main().
+   }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool 
+ValueInternalArray::equals( const IteratorState &x, 
+                            const IteratorState &other )
+{
+   return x.array_ == other.array_  
+          &&  x.currentItemIndex_ == other.currentItemIndex_  
+          &&  x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void 
+ValueInternalArray::increment( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      != it.array_->size_,
+      "ValueInternalArray::increment(): moving iterator beyond end" );
+   ++(it.currentItemIndex_);
+   if ( it.currentItemIndex_ == itemsPerPage )
+   {
+      it.currentItemIndex_ = 0;
+      ++(it.currentPageIndex_);
+   }
+}
+
+
+void 
+ValueInternalArray::decrement( IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&  it.currentPageIndex_ == it.array_->pages_ 
+                        &&  it.currentItemIndex_ == 0,
+      "ValueInternalArray::decrement(): moving iterator beyond end" );
+   if ( it.currentItemIndex_ == 0 )
+   {
+      it.currentItemIndex_ = itemsPerPage-1;
+      --(it.currentPageIndex_);
+   }
+   else
+   {
+      --(it.currentItemIndex_);
+   }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+   return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+   JSON_ASSERT_MESSAGE( it.array_  &&
+      (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+      < it.array_->size_,
+      "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+   return unsafeDereference( it );
+}
+
+void 
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = 0;
+   it.currentPageIndex_ = pages_;
+}
+
+
+void 
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+   it.array_ = const_cast<ValueInternalArray *>( this );
+   it.currentItemIndex_ = index % itemsPerPage;
+   it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void 
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+   makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+   : pages_( 0 )
+   , size_( 0 )
+   , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+   : pages_( 0 )
+   , pageCount_( 0 )
+   , size_( other.size_ )
+{
+   PageIndex minNewPages = other.size_ / itemsPerPage;
+   arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+   JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, 
+                        "ValueInternalArray::reserve(): bad reallocation" );
+   IteratorState itOther;
+   other.makeBeginIterator( itOther );
+   Value *value;
+   for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+   {
+      if ( index % itemsPerPage == 0 )
+      {
+         PageIndex pageIndex = index / itemsPerPage;
+         value = arrayAllocator()->allocateArrayPage();
+         pages_[pageIndex] = value;
+      }
+      new (value) Value( dereference( itOther ) );
+   }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+   ValueInternalArray temp( other );
+   swap( temp );
+   return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+   // destroy all constructed items
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it);
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      value->~Value();
+   }
+   // release all pages
+   PageIndex lastPageIndex = size_ / itemsPerPage;
+   for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+      arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+   // release pages index
+   arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void 
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+   Value **tempPages = pages_;
+   pages_ = other.pages_;
+   other.pages_ = tempPages;
+   ArrayIndex tempSize = size_;
+   size_ = other.size_;
+   other.size_ = tempSize;
+   PageIndex tempPageCount = pageCount_;
+   pageCount_ = other.pageCount_;
+   other.pageCount_ = tempPageCount;
+}
+
+void 
+ValueInternalArray::clear()
+{
+   ValueInternalArray dummy;
+   swap( dummy );
+}
+
+
+void 
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize < size_ )
+   {
+      IteratorState it;
+      IteratorState itEnd;
+      makeIterator( it, newSize );
+      makeIterator( itEnd, size_ );
+      for ( ; !equals(it,itEnd); increment(it) )
+      {
+         Value *value = &dereference(it);
+         value->~Value();
+      }
+      PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+      PageIndex lastPageIndex = size_ / itemsPerPage;
+      for ( ; pageIndex < lastPageIndex; ++pageIndex )
+         arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+      size_ = newSize;
+   }
+   else if ( newSize > size_ )
+      resolveReference( newSize );
+}
+
+
+void 
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+   // Need to enlarge page index ?
+   if ( index >= pageCount_ * itemsPerPage )
+   {
+      PageIndex minNewPages = (index + 1) / itemsPerPage;
+      arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+      JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+   }
+
+   // Need to allocate new pages ?
+   ArrayIndex nextPageIndex = 
+      (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+                                  : size_;
+   if ( nextPageIndex <= index )
+   {
+      PageIndex pageIndex = nextPageIndex / itemsPerPage;
+      PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+      for ( ; pageToAllocate-- > 0; ++pageIndex )
+         pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+   }
+
+   // Initialize all new entries
+   IteratorState it;
+   IteratorState itEnd;
+   makeIterator( it, size_ );
+   size_ = index + 1;
+   makeIterator( itEnd, size_ );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      Value *value = &dereference(it);
+      new (value) Value(); // Construct a default value using placement new
+   }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+   if ( index >= size_ )
+      makeIndexValid( index );
+   return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+   if ( index >= size_ )
+      return 0;
+   return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::size() const
+{
+   return size_;
+}
+
+int 
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+   return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex 
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+   if ( !iterator.array_ )
+      return ArrayIndex(-1);
+   return ArrayIndex(
+      (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage 
+      + iterator.currentItemIndex_ );
+}
+
+
+int 
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+   int sizeDiff( size_ - other.size_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   
+   for ( ArrayIndex index =0; index < size_; ++index )
+   {
+      int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( 
+         other.pages_[index/itemsPerPage][index%itemsPerPage] );
+      if ( diff != 0 )
+         return diff;
+   }
+   return 0;
+}

+ 607 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_internalmap.inl

@@ -0,0 +1,607 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+   * This optimization is used by the fast allocator.
+   */
+ValueInternalLink::ValueInternalLink()
+   : previous_( 0 )
+   , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{ 
+   for ( int index =0; index < itemPerLink; ++index )
+   {
+      if ( !items_[index].isItemAvailable() )
+      {
+         if ( !items_[index].isMemberNameStatic() )
+            free( keys_[index] );
+      }
+      else
+         break;
+   }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      return new ValueInternalMap();
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      return new ValueInternalMap( other );
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      delete map;
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      return new ValueInternalLink();
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      delete link;
+   }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+   virtual ValueInternalMap *newMap()
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap(); // placement new
+      return map;
+   }
+
+   virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+   {
+      ValueInternalMap *map = mapsAllocator_.allocate();
+      new (map) ValueInternalMap( other ); // placement new
+      return map;
+   }
+
+   virtual void destructMap( ValueInternalMap *map )
+   {
+      if ( map )
+      {
+         map->~ValueInternalMap();
+         mapsAllocator_.release( map );
+      }
+   }
+
+   virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+   {
+      return new ValueInternalLink[size];
+   }
+
+   virtual void releaseMapBuckets( ValueInternalLink *links )
+   {
+      delete [] links;
+   }
+
+   virtual ValueInternalLink *allocateMapLink()
+   {
+      ValueInternalLink *link = linksAllocator_.allocate();
+      memset( link, 0, sizeof(ValueInternalLink) );
+      return link;
+   }
+
+   virtual void releaseMapLink( ValueInternalLink *link )
+   {
+      link->~ValueInternalLink();
+      linksAllocator_.release( link );
+   }
+private:
+   BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+   BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+   static DefaultValueMapAllocator defaultAllocator;
+   static ValueMapAllocator *mapAllocator = &defaultAllocator;
+   return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+   DummyMapAllocatorInitializer() 
+   {
+      mapAllocator();      // ensure mapAllocator() statics are initialized before main().
+   }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map. 
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+   : buckets_( 0 )
+   , tailLink_( 0 )
+   , bucketsSize_( 0 )
+   , itemCount_( 0 )
+{
+   reserve( other.itemCount_ );
+   IteratorState it;
+   IteratorState itEnd;
+   other.makeBeginIterator( it );
+   other.makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      bool isStatic;
+      const char *memberName = key( it, isStatic );
+      const Value &aValue = value( it );
+      resolveReference(memberName, isStatic) = aValue;
+   }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+   ValueInternalMap dummy( other );
+   swap( dummy );
+   return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+   if ( buckets_ )
+   {
+      for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+      {
+         ValueInternalLink *link = buckets_[bucketIndex].next_;
+         while ( link )
+         {
+            ValueInternalLink *linkToRelease = link;
+            link = link->next_;
+            mapAllocator()->releaseMapLink( linkToRelease );
+         }
+      }
+      mapAllocator()->releaseMapBuckets( buckets_ );
+   }
+}
+
+
+void 
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+   ValueInternalLink *tempBuckets = buckets_;
+   buckets_ = other.buckets_;
+   other.buckets_ = tempBuckets;
+   ValueInternalLink *tempTailLink = tailLink_;
+   tailLink_ = other.tailLink_;
+   other.tailLink_ = tempTailLink;
+   BucketIndex tempBucketsSize = bucketsSize_;
+   bucketsSize_ = other.bucketsSize_;
+   other.bucketsSize_ = tempBucketsSize;
+   BucketIndex tempItemCount = itemCount_;
+   itemCount_ = other.itemCount_;
+   other.itemCount_ = tempItemCount;
+}
+
+
+void 
+ValueInternalMap::clear()
+{
+   ValueInternalMap dummy;
+   swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex 
+ValueInternalMap::size() const
+{
+   return itemCount_;
+}
+
+bool 
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+   return reserve( itemCount_ + growth );
+}
+
+bool 
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+   if ( !buckets_  &&  newItemCount > 0 )
+   {
+      buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+      bucketsSize_ = 1;
+      tailLink_ = &buckets_[0];
+   }
+//   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+   return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+   if ( !bucketsSize_ )
+      return 0;
+   HashKey hashedKey = hash( key );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( const ValueInternalLink *current = &buckets_[bucketIndex]; 
+         current != 0; 
+         current = current->next_ )
+   {
+      for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( current->items_[index].isItemAvailable() )
+            return 0;
+         if ( strcmp( key, current->keys_[index] ) == 0 )
+            return &current->items_[index];
+      }
+   }
+   return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+   const ValueInternalMap *constThis = this;
+   return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+                                    bool isStatic )
+{
+   HashKey hashedKey = hash( key );
+   if ( bucketsSize_ )
+   {
+      BucketIndex bucketIndex = hashedKey % bucketsSize_;
+      ValueInternalLink **previous = 0;
+      BucketIndex index;
+      for ( ValueInternalLink *current = &buckets_[bucketIndex]; 
+            current != 0; 
+            previous = &current->next_, current = current->next_ )
+      {
+         for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+         {
+            if ( current->items_[index].isItemAvailable() )
+               return setNewItem( key, isStatic, current, index );
+            if ( strcmp( key, current->keys_[index] ) == 0 )
+               return current->items_[index];
+         }
+      }
+   }
+
+   reserveDelta( 1 );
+   return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void 
+ValueInternalMap::remove( const char *key )
+{
+   HashKey hashedKey = hash( key );
+   if ( !bucketsSize_ )
+      return;
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   for ( ValueInternalLink *link = &buckets_[bucketIndex]; 
+         link != 0; 
+         link = link->next_ )
+   {
+      BucketIndex index;
+      for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+      {
+         if ( link->items_[index].isItemAvailable() )
+            return;
+         if ( strcmp( key, link->keys_[index] ) == 0 )
+         {
+            doActualRemove( link, index, bucketIndex );
+            return;
+         }
+      }
+   }
+}
+
+void 
+ValueInternalMap::doActualRemove( ValueInternalLink *link, 
+                                  BucketIndex index,
+                                  BucketIndex bucketIndex )
+{
+   // find last item of the bucket and swap it with the 'removed' one.
+   // set removed items flags to 'available'.
+   // if last page only contains 'available' items, then desallocate it (it's empty)
+   ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+   BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+   for ( ;   
+         lastItemIndex < ValueInternalLink::itemPerLink; 
+         ++lastItemIndex ) // may be optimized with dicotomic search
+   {
+      if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+         break;
+   }
+   
+   BucketIndex lastUsedIndex = lastItemIndex - 1;
+   Value *valueToDelete = &link->items_[index];
+   Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+   if ( valueToDelete != valueToPreserve )
+      valueToDelete->swap( *valueToPreserve );
+   if ( lastUsedIndex == 0 )  // page is now empty
+   {  // remove it from bucket linked list and delete it.
+      ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+      if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
+      {
+         mapAllocator()->releaseMapLink( lastLink );
+         linkPreviousToLast->next_ = 0;
+         lastLink = linkPreviousToLast;
+      }
+   }
+   else
+   {
+      Value dummy;
+      valueToPreserve->swap( dummy ); // restore deleted to default Value.
+      valueToPreserve->setItemUsed( false );
+   }
+   --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+   if ( bucketIndex == bucketsSize_ - 1 )
+      return tailLink_;
+   ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+   if ( !previous )
+      previous = &buckets_[bucketIndex];
+   return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key, 
+                              bool isStatic,
+                              ValueInternalLink *link, 
+                              BucketIndex index )
+{
+   char *duplicatedKey = valueAllocator()->makeMemberName( key );
+   ++itemCount_;
+   link->keys_[index] = duplicatedKey;
+   link->items_[index].setItemUsed();
+   link->items_[index].setMemberNameIsStatic( isStatic );
+   return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key, 
+                             bool isStatic, 
+                             HashKey hashedKey )
+{
+   JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+   BucketIndex bucketIndex = hashedKey % bucketsSize_;
+   ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+   ValueInternalLink *link = previousLink;
+   BucketIndex index;
+   for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+   {
+      if ( link->items_[index].isItemAvailable() )
+         break;
+   }
+   if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+   {
+      ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+      index = 0;
+      link->next_ = newLink;
+      previousLink = newLink;
+      link = newLink;
+   }
+   return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey 
+ValueInternalMap::hash( const char *key ) const
+{
+   HashKey hash = 0;
+   while ( *key )
+      hash += *key++ * 37;
+   return hash;
+}
+
+
+int 
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+   int sizeDiff( itemCount_ - other.itemCount_ );
+   if ( sizeDiff != 0 )
+      return sizeDiff;
+   // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+   IteratorState it;
+   IteratorState itEnd;
+   makeBeginIterator( it );
+   makeEndIterator( itEnd );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      if ( !other.find( key( it ) ) )
+         return 1;
+   }
+
+   // All keys are equals, let's compare values
+   makeBeginIterator( it );
+   for ( ; !equals(it,itEnd); increment(it) )
+   {
+      const Value *otherValue = other.find( key( it ) );
+      int valueDiff = value(it).compare( *otherValue );
+      if ( valueDiff != 0 )
+         return valueDiff;
+   }
+   return 0;
+}
+
+
+void 
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = 0;
+   it.itemIndex_ = 0;
+   it.link_ = buckets_;
+}
+
+
+void 
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+   it.map_ = const_cast<ValueInternalMap *>( this );
+   it.bucketIndex_ = bucketsSize_;
+   it.itemIndex_ = 0;
+   it.link_ = 0;
+}
+
+
+bool 
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+   return x.map_ == other.map_  
+          &&  x.bucketIndex_ == other.bucketIndex_  
+          &&  x.link_ == other.link_
+          &&  x.itemIndex_ == other.itemIndex_;
+}
+
+
+void 
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+   ++iterator.bucketIndex_;
+   JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+      "ValueInternalMap::increment(): attempting to iterate beyond end." );
+   if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+      iterator.link_ = 0;
+   else
+      iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+   iterator.itemIndex_ = 0;
+}
+
+
+void 
+ValueInternalMap::increment( IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+   ++iterator.itemIndex_;
+   if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+   {
+      JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+         "ValueInternalMap::increment(): attempting to iterate beyond end." );
+      iterator.link_ = iterator.link_->next_;
+      if ( iterator.link_ == 0 )
+         incrementBucket( iterator );
+   }
+   else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+   {
+      incrementBucket( iterator );
+   }
+}
+
+
+void 
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+   if ( iterator.itemIndex_ == 0 )
+   {
+      JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+      if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+      {
+         JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+         --(iterator.bucketIndex_);
+      }
+      iterator.link_ = iterator.link_->previous_;
+      iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+   }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+   return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+   JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+   return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int 
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+   int offset = 0;
+   IteratorState it = x;
+   while ( !equals( it, y ) )
+      increment( it );
+   return offset;
+}

+ 892 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_reader.cpp

@@ -0,0 +1,892 @@
+#include <json/reader.h>
+#include <json/value.h>
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// QNX is strict about declaring C symbols in the std namespace.
+#ifdef __QNXNTO__
+using std::memcpy;
+using std::sprintf;
+using std::sscanf;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+   : allowComments_( true )
+   , strictRoot_( false )
+{
+}
+
+
+Features 
+Features::all()
+{
+   return Features();
+}
+
+
+Features 
+Features::strictMode()
+{
+   Features features;
+   features.allowComments_ = false;
+   features.strictRoot_ = true;
+   return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
+}
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
+}
+
+
+static bool 
+containsNewLine( Reader::Location begin, 
+                 Reader::Location end )
+{
+   for ( ;begin < end; ++begin )
+      if ( *begin == '\n'  ||  *begin == '\r' )
+         return true;
+   return false;
+}
+
+static std::string codePointToUTF8(unsigned int cp)
+{
+   std::string result;
+   
+   // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+   if (cp <= 0x7f) 
+   {
+      result.resize(1);
+      result[0] = static_cast<char>(cp);
+   } 
+   else if (cp <= 0x7FF) 
+   {
+      result.resize(2);
+      result[1] = static_cast<char>(0x80 | (0x3f & cp));
+      result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+   } 
+   else if (cp <= 0xFFFF) 
+   {
+      result.resize(3);
+      result[2] = static_cast<char>(0x80 | (0x3f & cp));
+      result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+      result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+   }
+   else if (cp <= 0x10FFFF) 
+   {
+      result.resize(4);
+      result[3] = static_cast<char>(0x80 | (0x3f & cp));
+      result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+      result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+      result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+   }
+
+   return result;
+}
+
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+   : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+   : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document, 
+               Value &root,
+               bool collectComments )
+{
+   document_ = document;
+   const char *begin = document_.c_str();
+   const char *end = begin + document_.length();
+   return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+               Value &root,
+               bool collectComments )
+{
+   //std::istream_iterator<char> begin(sin);
+   //std::istream_iterator<char> end;
+   // Those would allow streamed input from a file, if parse() were a
+   // template function.
+
+   // Since std::string is reference-counted, this at least does not
+   // create an extra copy.
+   std::string doc;
+   std::getline(sin, doc, (char)EOF);
+   return parse( doc, root, collectComments );
+}
+
+bool 
+Reader::parse( const char *beginDoc, const char *endDoc, 
+               Value &root,
+               bool collectComments )
+{
+   if ( !features_.allowComments_ )
+   {
+      collectComments = false;
+   }
+
+   begin_ = beginDoc;
+   end_ = endDoc;
+   collectComments_ = collectComments;
+   current_ = begin_;
+   lastValueEnd_ = 0;
+   lastValue_ = 0;
+   commentsBefore_ = "";
+   errors_.clear();
+   while ( !nodes_.empty() )
+      nodes_.pop();
+   nodes_.push( &root );
+   
+   bool successful = readValue();
+   Token token;
+   skipCommentTokens( token );
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+      root.setComment( commentsBefore_, commentAfter );
+   if ( features_.strictRoot_ )
+   {
+      if ( !root.isArray()  &&  !root.isObject() )
+      {
+         // Set error location to start of doc, ideally should be first token found in doc
+         token.type_ = tokenError;
+         token.start_ = beginDoc;
+         token.end_ = endDoc;
+         addError( "A valid JSON document must be either an array or an object value.",
+                   token );
+         return false;
+      }
+   }
+   return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+   Token token;
+   skipCommentTokens( token );
+   bool successful = true;
+
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+   {
+      currentValue().setComment( commentsBefore_, commentBefore );
+      commentsBefore_ = "";
+   }
+
+
+   switch ( token.type_ )
+   {
+   case tokenObjectBegin:
+      successful = readObject( token );
+      break;
+   case tokenArrayBegin:
+      successful = readArray( token );
+      break;
+   case tokenNumber:
+      successful = decodeNumber( token );
+      break;
+   case tokenString:
+      successful = decodeString( token );
+      break;
+   case tokenTrue:
+      currentValue() = true;
+      break;
+   case tokenFalse:
+      currentValue() = false;
+      break;
+   case tokenNull:
+      currentValue() = Value();
+      break;
+   default:
+      return addError( "Syntax error: value, object or array expected.", token );
+   }
+
+   if ( collectComments_ )
+   {
+      lastValueEnd_ = current_;
+      lastValue_ = &currentValue();
+   }
+
+   return successful;
+}
+
+
+void 
+Reader::skipCommentTokens( Token &token )
+{
+   if ( features_.allowComments_ )
+   {
+      do
+      {
+         readToken( token );
+      }
+      while ( token.type_ == tokenComment );
+   }
+   else
+   {
+      readToken( token );
+   }
+}
+
+
+bool 
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+   readToken( token );
+   if ( token.type_ != type )
+      return addError( message, token );
+   return true;
+}
+
+
+bool 
+Reader::readToken( Token &token )
+{
+   skipSpaces();
+   token.start_ = current_;
+   Char c = getNextChar();
+   bool ok = true;
+   switch ( c )
+   {
+   case '{':
+      token.type_ = tokenObjectBegin;
+      break;
+   case '}':
+      token.type_ = tokenObjectEnd;
+      break;
+   case '[':
+      token.type_ = tokenArrayBegin;
+      break;
+   case ']':
+      token.type_ = tokenArrayEnd;
+      break;
+   case '"':
+      token.type_ = tokenString;
+      ok = readString();
+      break;
+   case '/':
+      token.type_ = tokenComment;
+      ok = readComment();
+      break;
+   case '0':
+   case '1':
+   case '2':
+   case '3':
+   case '4':
+   case '5':
+   case '6':
+   case '7':
+   case '8':
+   case '9':
+   case '-':
+      token.type_ = tokenNumber;
+      readNumber();
+      break;
+   case 't':
+      token.type_ = tokenTrue;
+      ok = match( "rue", 3 );
+      break;
+   case 'f':
+      token.type_ = tokenFalse;
+      ok = match( "alse", 4 );
+      break;
+   case 'n':
+      token.type_ = tokenNull;
+      ok = match( "ull", 3 );
+      break;
+   case ',':
+      token.type_ = tokenArraySeparator;
+      break;
+   case ':':
+      token.type_ = tokenMemberSeparator;
+      break;
+   case 0:
+      token.type_ = tokenEndOfStream;
+      break;
+   default:
+      ok = false;
+      break;
+   }
+   if ( !ok )
+      token.type_ = tokenError;
+   token.end_ = current_;
+   return true;
+}
+
+
+void 
+Reader::skipSpaces()
+{
+   while ( current_ != end_ )
+   {
+      Char c = *current_;
+      if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
+         ++current_;
+      else
+         break;
+   }
+}
+
+
+bool 
+Reader::match( Location pattern, 
+               int patternLength )
+{
+   if ( end_ - current_ < patternLength )
+      return false;
+   int index = patternLength;
+   while ( index-- )
+      if ( current_[index] != pattern[index] )
+         return false;
+   current_ += patternLength;
+   return true;
+}
+
+
+bool
+Reader::readComment()
+{
+   Location commentBegin = current_ - 1;
+   Char c = getNextChar();
+   bool successful = false;
+   if ( c == '*' )
+      successful = readCStyleComment();
+   else if ( c == '/' )
+      successful = readCppStyleComment();
+   if ( !successful )
+      return false;
+
+   if ( collectComments_ )
+   {
+      CommentPlacement placement = commentBefore;
+      if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
+      {
+         if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
+            placement = commentAfterOnSameLine;
+      }
+
+      addComment( commentBegin, current_, placement );
+   }
+   return true;
+}
+
+
+void 
+Reader::addComment( Location begin, 
+                    Location end, 
+                    CommentPlacement placement )
+{
+   assert( collectComments_ );
+   if ( placement == commentAfterOnSameLine )
+   {
+      assert( lastValue_ != 0 );
+      lastValue_->setComment( std::string( begin, end ), placement );
+   }
+   else
+   {
+      if ( !commentsBefore_.empty() )
+         commentsBefore_ += "\n";
+      commentsBefore_ += std::string( begin, end );
+   }
+}
+
+
+bool 
+Reader::readCStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if ( c == '*'  &&  *current_ == '/' )
+         break;
+   }
+   return getNextChar() == '/';
+}
+
+
+bool 
+Reader::readCppStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if (  c == '\r'  ||  c == '\n' )
+         break;
+   }
+   return true;
+}
+
+
+void 
+Reader::readNumber()
+{
+   while ( current_ != end_ )
+   {
+      if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
+           !in( *current_, '.', 'e', 'E', '+', '-' ) )
+         break;
+      ++current_;
+   }
+}
+
+bool
+Reader::readString()
+{
+   Char c = 0;
+   while ( current_ != end_ )
+   {
+      c = getNextChar();
+      if ( c == '\\' )
+         getNextChar();
+      else if ( c == '"' )
+         break;
+   }
+   return c == '"';
+}
+
+
+bool 
+Reader::readObject( Token &tokenStart )
+{
+   Token tokenName;
+   std::string name;
+   currentValue() = Value( objectValue );
+   while ( readToken( tokenName ) )
+   {
+      bool initialTokenOk = true;
+      while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
+         initialTokenOk = readToken( tokenName );
+      if  ( !initialTokenOk )
+         break;
+      if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
+         return true;
+      if ( tokenName.type_ != tokenString )
+         break;
+      
+      name = "";
+      if ( !decodeString( tokenName, name ) )
+         return recoverFromError( tokenObjectEnd );
+
+      Token colon;
+      if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
+      {
+         return addErrorAndRecover( "Missing ':' after object member name", 
+                                    colon, 
+                                    tokenObjectEnd );
+      }
+      Value &value = currentValue()[ name ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenObjectEnd );
+
+      Token comma;
+      if ( !readToken( comma )
+            ||  ( comma.type_ != tokenObjectEnd  &&  
+                  comma.type_ != tokenArraySeparator &&
+		  comma.type_ != tokenComment ) )
+      {
+         return addErrorAndRecover( "Missing ',' or '}' in object declaration", 
+                                    comma, 
+                                    tokenObjectEnd );
+      }
+      bool finalizeTokenOk = true;
+      while ( comma.type_ == tokenComment &&
+              finalizeTokenOk )
+         finalizeTokenOk = readToken( comma );
+      if ( comma.type_ == tokenObjectEnd )
+         return true;
+   }
+   return addErrorAndRecover( "Missing '}' or object member name", 
+                              tokenName, 
+                              tokenObjectEnd );
+}
+
+
+bool 
+Reader::readArray( Token &tokenStart )
+{
+   currentValue() = Value( arrayValue );
+   skipSpaces();
+   if ( *current_ == ']' ) // empty array
+   {
+      Token endArray;
+      readToken( endArray );
+      return true;
+   }
+   int index = 0;
+   while ( true )
+   {
+      Value &value = currentValue()[ index++ ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenArrayEnd );
+
+      Token token;
+      // Accept Comment after last item in the array.
+      ok = readToken( token );
+      while ( token.type_ == tokenComment  &&  ok )
+      {
+         ok = readToken( token );
+      }
+      bool badTokenType = ( token.type_ == tokenArraySeparator  &&  
+                            token.type_ == tokenArrayEnd );
+      if ( !ok  ||  badTokenType )
+      {
+         return addErrorAndRecover( "Missing ',' or ']' in array declaration", 
+                                    token, 
+                                    tokenArrayEnd );
+      }
+      if ( token.type_ == tokenArrayEnd )
+         break;
+   }
+   return true;
+}
+
+
+bool 
+Reader::decodeNumber( Token &token )
+{
+   bool isDouble = false;
+   for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+   {
+      isDouble = isDouble  
+                 ||  in( *inspect, '.', 'e', 'E', '+' )  
+                 ||  ( *inspect == '-'  &&  inspect != token.start_ );
+   }
+   if ( isDouble )
+      return decodeDouble( token );
+   Location current = token.start_;
+   bool isNegative = *current == '-';
+   if ( isNegative )
+      ++current;
+   Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) 
+                                       : Value::maxUInt) / 10;
+   Value::UInt value = 0;
+   while ( current < token.end_ )
+   {
+      Char c = *current++;
+      if ( c < '0'  ||  c > '9' )
+         return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+      if ( value >= threshold )
+         return decodeDouble( token );
+      value = value * 10 + Value::UInt(c - '0');
+   }
+   if ( isNegative )
+      currentValue() = -Value::Int( value );
+   else if ( value <= Value::UInt(Value::maxInt) )
+      currentValue() = Value::Int( value );
+   else
+      currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeDouble( Token &token )
+{
+   double value = 0;
+   const int bufferSize = 32;
+   int count;
+   int length = int(token.end_ - token.start_);
+   if ( length <= bufferSize )
+   {
+      Char buffer[bufferSize];
+      memcpy( buffer, token.start_, length );
+      buffer[length] = 0;
+      count = sscanf( buffer, "%lf", &value );
+   }
+   else
+   {
+      std::string buffer( token.start_, token.end_ );
+      count = sscanf( buffer.c_str(), "%lf", &value );
+   }
+
+   if ( count != 1 )
+      return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+   currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token )
+{
+   std::string decoded;
+   if ( !decodeString( token, decoded ) )
+      return false;
+   currentValue() = decoded;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token, std::string &decoded )
+{
+   decoded.reserve( token.end_ - token.start_ - 2 );
+   Location current = token.start_ + 1; // skip '"'
+   Location end = token.end_ - 1;      // do not include '"'
+   while ( current != end )
+   {
+      Char c = *current++;
+      if ( c == '"' )
+         break;
+      else if ( c == '\\' )
+      {
+         if ( current == end )
+            return addError( "Empty escape sequence in string", token, current );
+         Char escape = *current++;
+         switch ( escape )
+         {
+         case '"': decoded += '"'; break;
+         case '/': decoded += '/'; break;
+         case '\\': decoded += '\\'; break;
+         case 'b': decoded += '\b'; break;
+         case 'f': decoded += '\f'; break;
+         case 'n': decoded += '\n'; break;
+         case 'r': decoded += '\r'; break;
+         case 't': decoded += '\t'; break;
+         case 'u':
+            {
+               unsigned int unicode;
+               if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+                  return false;
+               decoded += codePointToUTF8(unicode);
+            }
+            break;
+         default:
+            return addError( "Bad escape sequence in string", token, current );
+         }
+      }
+      else
+      {
+         decoded += c;
+      }
+   }
+   return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+
+   if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+      return false;
+   if (unicode >= 0xD800 && unicode <= 0xDBFF)
+   {
+      // surrogate pairs
+      if (end - current < 6)
+         return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+      unsigned int surrogatePair;
+      if (*(current++) == '\\' && *(current++)== 'u')
+      {
+         if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+         {
+            unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+         } 
+         else
+            return false;
+      } 
+      else
+         return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+   }
+   return true;
+}
+
+bool 
+Reader::decodeUnicodeEscapeSequence( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+   if ( end - current < 4 )
+      return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+   unicode = 0;
+   for ( int index =0; index < 4; ++index )
+   {
+      Char c = *current++;
+      unicode *= 16;
+      if ( c >= '0'  &&  c <= '9' )
+         unicode += c - '0';
+      else if ( c >= 'a'  &&  c <= 'f' )
+         unicode += c - 'a' + 10;
+      else if ( c >= 'A'  &&  c <= 'F' )
+         unicode += c - 'A' + 10;
+      else
+         return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+   }
+   return true;
+}
+
+
+bool 
+Reader::addError( const std::string &message, 
+                  Token &token,
+                  Location extra )
+{
+   ErrorInfo info;
+   info.token_ = token;
+   info.message_ = message;
+   info.extra_ = extra;
+   errors_.push_back( info );
+   return false;
+}
+
+
+bool 
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+   int errorCount = int(errors_.size());
+   Token skip;
+   while ( true )
+   {
+      if ( !readToken(skip) )
+         errors_.resize( errorCount ); // discard errors caused by recovery
+      if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
+         break;
+   }
+   errors_.resize( errorCount );
+   return false;
+}
+
+
+bool 
+Reader::addErrorAndRecover( const std::string &message, 
+                            Token &token,
+                            TokenType skipUntilToken )
+{
+   addError( message, token );
+   return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+   return *(nodes_.top());
+}
+
+
+Reader::Char 
+Reader::getNextChar()
+{
+   if ( current_ == end_ )
+      return 0;
+   return *current_++;
+}
+
+
+void 
+Reader::getLocationLineAndColumn( Location location,
+                                  int &line,
+                                  int &column ) const
+{
+   Location current = begin_;
+   Location lastLineStart = current;
+   line = 0;
+   while ( current < location  &&  current != end_ )
+   {
+      Char c = *current++;
+      if ( c == '\r' )
+      {
+         if ( *current == '\n' )
+            ++current;
+         lastLineStart = current;
+         ++line;
+      }
+      else if ( c == '\n' )
+      {
+         lastLineStart = current;
+         ++line;
+      }
+   }
+   // column & line start at 1
+   column = int(location - lastLineStart) + 1;
+   ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+   int line, column;
+   getLocationLineAndColumn( location, line, column );
+   char buffer[18+16+16+1];
+   sprintf( buffer, "Line %d, Column %d", line, column );
+   return buffer;
+}
+
+
+std::string 
+Reader::getFormatedErrorMessages() const
+{
+   std::string formattedMessage;
+   for ( Errors::const_iterator itError = errors_.begin();
+         itError != errors_.end();
+         ++itError )
+   {
+      const ErrorInfo &error = *itError;
+      formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+      formattedMessage += "  " + error.message_ + "\n";
+      if ( error.extra_ )
+         formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+   }
+   return formattedMessage;
+}
+
+
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+    Json::Reader reader;
+    bool ok = reader.parse(sin, root, true);
+    //JSON_ASSERT( ok );
+    if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
+    return sin;
+}
+
+
+} // namespace Json

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1726 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_value.cpp


+ 292 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_valueiterator.inl

@@ -0,0 +1,292 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   : current_()
+   , isNull_( true )
+{
+}
+#else
+   : isArray_( true )
+   , isNull_( true )
+{
+   iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+   : current_( current )
+   , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+   : isArray_( true )
+{
+   iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+   : isArray_( false )
+{
+   iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   return current_->second;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::dereference( iterator_.array_ );
+   return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ++current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::increment( iterator_.array_ );
+   ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   --current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::decrement( iterator_.array_ );
+   ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type 
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+   return current_ - other.current_;
+# else
+   // Iterator for null value are initialized using the default
+   // constructor, which initialize current_ to the default
+   // std::map::iterator. As begin() and end() are two instance 
+   // of the default std::map::iterator, they can not be compared.
+   // To allow this, we handle this comparison specifically.
+   if ( isNull_  &&  other.isNull_ )
+   {
+      return 0;
+   }
+
+
+   // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+   // which is the one used by default).
+   // Using a portable hand-made version for non random iterator instead:
+   //   return difference_type( std::distance( current_, other.current_ ) );
+   difference_type myDistance = 0;
+   for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+   {
+      ++myDistance;
+   }
+   return myDistance;
+# endif
+#else
+   if ( isArray_ )
+      return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool 
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   if ( isNull_ )
+   {
+      return other.isNull_;
+   }
+   return current_ == other.current_;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   current_ = other.current_;
+#else
+   if ( isArray_ )
+      iterator_.array_ = other.iterator_.array_;
+   iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value 
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( czstring.c_str() )
+   {
+      if ( czstring.isStaticString() )
+         return Value( StaticString( czstring.c_str() ) );
+      return Value( czstring.c_str() );
+   }
+   return Value( czstring.index() );
+#else
+   if ( isArray_ )
+      return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+   bool isStatic;
+   const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+   if ( isStatic )
+      return Value( StaticString( memberName ) );
+   return Value( memberName );
+#endif
+}
+
+
+UInt 
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( !czstring.c_str() )
+      return czstring.index();
+   return Value::UInt( -1 );
+#else
+   if ( isArray_ )
+      return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+   return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const char *name = (*current_).first.c_str();
+   return name ? name : "";
+#else
+   if ( !isArray_ )
+      return ValueInternalMap::key( iterator_.map_ );
+   return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+   copy( other );
+   return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+   copy( other );
+   return *this;
+}

+ 829 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/json_writer.cpp

@@ -0,0 +1,829 @@
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool isControlCharacter(char ch)
+{
+   return ch > 0 && ch <= 0x1F;
+}
+
+static bool containsControlCharacter( const char* str )
+{
+   while ( *str ) 
+   {
+      if ( isControlCharacter( *(str++) ) )
+         return true;
+   }
+   return false;
+}
+static void uintToString( unsigned int value, 
+                          char *&current )
+{
+   *--current = 0;
+   do
+   {
+      *--current = (value % 10) + '0';
+      value /= 10;
+   }
+   while ( value != 0 );
+}
+
+std::string valueToString( Int value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   bool isNegative = value < 0;
+   if ( isNegative )
+      value = -value;
+   uintToString( UInt(value), current );
+   if ( isNegative )
+      *--current = '-';
+   assert( current >= buffer );
+   return current;
+}
+
+
+std::string valueToString( UInt value )
+{
+   char buffer[32];
+   char *current = buffer + sizeof(buffer);
+   uintToString( value, current );
+   assert( current >= buffer );
+   return current;
+}
+
+std::string valueToString( double value )
+{
+   char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. 
+   sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
+#else	
+   sprintf(buffer, "%#.16g", value); 
+#endif
+   char* ch = buffer + strlen(buffer) - 1;
+   if (*ch != '0') return buffer; // nothing to truncate, so save time
+   while(ch > buffer && *ch == '0'){
+     --ch;
+   }
+   char* last_nonzero = ch;
+   while(ch >= buffer){
+     switch(*ch){
+     case '0':
+     case '1':
+     case '2':
+     case '3':
+     case '4':
+     case '5':
+     case '6':
+     case '7':
+     case '8':
+     case '9':
+       --ch;
+       continue;
+     case '.':
+       // Truncate zeroes to save bytes in output, but keep one.
+       *(last_nonzero+2) = '\0';
+       return buffer;
+     default:
+       return buffer;
+     }
+   }
+   return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+   return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+   // Not sure how to handle unicode...
+   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
+      return std::string("\"") + value + "\"";
+   // We have to walk value and escape any special characters.
+   // Appending to std::string is not efficient, but this should be rare.
+   // (Note: forward slashes are *not* rare, but I am not escaping them.)
+   unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+   std::string result;
+   result.reserve(maxsize); // to avoid lots of mallocs
+   result += "\"";
+   for (const char* c=value; *c != 0; ++c)
+   {
+      switch(*c)
+      {
+         case '\"':
+            result += "\\\"";
+            break;
+         case '\\':
+            result += "\\\\";
+            break;
+         case '\b':
+            result += "\\b";
+            break;
+         case '\f':
+            result += "\\f";
+            break;
+         case '\n':
+            result += "\\n";
+            break;
+         case '\r':
+            result += "\\r";
+            break;
+         case '\t':
+            result += "\\t";
+            break;
+         //case '/':
+            // Even though \/ is considered a legal escape in JSON, a bare
+            // slash is also legal, so I see no reason to escape it.
+            // (I hope I am not misunderstanding something.
+            // blep notes: actually escaping \/ may be useful in javascript to avoid </ 
+            // sequence.
+            // Should add a flag to allow this compatibility mode and prevent this 
+            // sequence from occurring.
+         default:
+            if ( isControlCharacter( *c ) )
+            {
+               std::ostringstream oss;
+               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+               result += oss.str();
+            }
+            else
+            {
+               result += *c;
+            }
+            break;
+      }
+   }
+   result += "\"";
+   return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+   : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void 
+FastWriter::enableYAMLCompatibility()
+{
+   yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string 
+FastWriter::write( const Value &root )
+{
+   document_ = "";
+   writeValue( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+FastWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      document_ += "null";
+      break;
+   case intValue:
+      document_ += valueToString( value.asInt() );
+      break;
+   case uintValue:
+      document_ += valueToString( value.asUInt() );
+      break;
+   case realValue:
+      document_ += valueToString( value.asDouble() );
+      break;
+   case stringValue:
+      document_ += valueToQuotedString( value.asCString() );
+      break;
+   case booleanValue:
+      document_ += valueToString( value.asBool() );
+      break;
+   case arrayValue:
+      {
+         document_ += "[";
+         int size = value.size();
+         for ( int index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ",";
+            writeValue( value[index] );
+         }
+         document_ += "]";
+      }
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         document_ += "{";
+         for ( Value::Members::iterator it = members.begin(); 
+               it != members.end(); 
+               ++it )
+         {
+            const std::string &name = *it;
+            if ( it != members.begin() )
+               document_ += ",";
+            document_ += valueToQuotedString( name.c_str() );
+            document_ += yamlCompatiblityEnabled_ ? ": " 
+                                                  : ":";
+            writeValue( value[name] );
+         }
+         document_ += "}";
+      }
+      break;
+   }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+   : rightMargin_( 74 )
+   , indentSize_( 3 )
+{
+}
+
+
+std::string 
+StyledWriter::write( const Value &root )
+{
+   document_ = "";
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+StyledWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               document_ += " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               document_ += ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            document_ += ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         document_ += "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ", ";
+            document_ += childValues_[index];
+         }
+         document_ += " ]";
+      }
+   }
+}
+
+
+bool 
+StyledWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      document_ += value;
+}
+
+
+void 
+StyledWriter::writeIndent()
+{
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         document_ += '\n';
+   }
+   document_ += indentString_;
+}
+
+
+void 
+StyledWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   document_ += value;
+}
+
+
+void 
+StyledWriter::indent()
+{
+   indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void 
+StyledWriter::unindent()
+{
+   assert( int(indentString_.size()) >= indentSize_ );
+   indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void 
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   document_ += normalizeEOL( root.getComment( commentBefore ) );
+   document_ += "\n";
+}
+
+
+void 
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      document_ += "\n";
+      document_ += normalizeEOL( root.getComment( commentAfter ) );
+      document_ += "\n";
+   }
+}
+
+
+bool 
+StyledWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+   : document_(NULL)
+   , rightMargin_( 74 )
+   , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+   document_ = &out;
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   *document_ << "\n";
+   document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void 
+StyledStreamWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            while ( true )
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               *document_ << " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               *document_ << ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         while ( true )
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+	       writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            *document_ << ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         *document_ << "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               *document_ << ", ";
+            *document_ << childValues_[index];
+         }
+         *document_ << " ]";
+      }
+   }
+}
+
+
+bool 
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledStreamWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::writeIndent()
+{
+  /*
+    Some comments in this method would have been nice. ;-)
+
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         *document_ << '\n';
+   }
+  */
+   *document_ << '\n' << indentString_;
+}
+
+
+void 
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::indent()
+{
+   indentString_ += indentation_;
+}
+
+
+void 
+StyledStreamWriter::unindent()
+{
+   assert( indentString_.size() >= indentation_.size() );
+   indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void 
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   *document_ << normalizeEOL( root.getComment( commentBefore ) );
+   *document_ << "\n";
+}
+
+
+void 
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      *document_ << "\n";
+      *document_ << normalizeEOL( root.getComment( commentAfter ) );
+      *document_ << "\n";
+   }
+}
+
+
+bool 
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+   Json::StyledStreamWriter writer;
+   writer.write(sout, root);
+   return sout;
+}
+
+
+} // namespace Json

+ 320 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/plugin.cpp

@@ -0,0 +1,320 @@
+#include "plugin.h"
+#include "tokenizer.h"
+
+#ifdef _WINDOWS
+#include <windows.h>
+BOOL APIENTRY DllMain( HANDLE hModule,
+                       DWORD ul_reason_for_call,
+                       LPVOID lpReserved )
+{
+    return TRUE;
+}
+#else
+#include <errno.h>
+#include <string.h>
+
+extern int errno;
+#endif
+
+SendPluginEv SendPluginEvent;
+
+string g_GetSysErrMsg( void )
+{
+    string strError = "Unknown";
+    // Problem loading
+#ifdef _WINDOWS
+    int nErrorCode = GetLastError();
+    LPTSTR s;
+    if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL, nErrorCode, 0, ( LPTSTR ) &s, 0, NULL ) )
+    {
+        strError = s;
+    }
+    else
+    {
+        char szBuf[ 20 ];
+        _snprintf_s( szBuf, _countof(szBuf), 19, "%d", nErrorCode );
+        strError = szBuf;
+    }
+#else
+    char szError[80];
+    if ( strerror_r( errno, szError, sizeof(szError)  ) )
+    {
+        strError = "no description found";
+    }
+    else
+    {
+        strError = szError;
+    }
+#endif
+    return strError;
+}
+
+void g_sleep( unsigned int mseconds )
+{
+#ifdef _WINDOWS
+    Sleep( mseconds );
+#else
+    usleep( mseconds * 1000 );
+#endif
+}
+
+string& g_trim( string& str )
+{
+    // Whitespace characters
+    char whspc[] = " \t\r\n\v\f";
+
+    // Whack off first part
+    size_t pos = str.find_first_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( 0, pos, "" );
+
+    // Whack off trailing stuff
+    pos = str.find_last_not_of( whspc );
+
+    if ( pos != string::npos )
+        str.replace( pos + 1, str.length() - pos, "" );
+
+    return str;
+}
+
+void g_tokenize( const string& str, const string& delimiters, vector<string>& tokens )
+{
+    tokenize( str, tokens, delimiters );
+}
+
+char* SetEventFunc( SendPluginEv funcPtr )
+{
+    static char * szObjList = onGetObjList();
+    SendPluginEvent = funcPtr;
+    return szObjList;
+}
+
+
+const int nMAXSIZE = 512;
+char* g_pszRetVal = NULL;
+
+//-----------------------------------------------------------
+// Map from an object Id to an object instance
+//-----------------------------------------------------------
+typedef std::map<string, JSExt*> StringToJExt_T;
+
+//-----------------------------------------------------------
+// Map from a browser context to an id mapping
+//-----------------------------------------------------------
+typedef std::map<void*, StringToJExt_T*> VoidToMap_T;
+
+VoidToMap_T g_context2Map;
+
+class GlobalSharedModule
+{
+
+public:
+    GlobalSharedModule( void )
+    {
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    ~GlobalSharedModule()
+    {
+        delete [] g_pszRetVal;
+
+        VoidToMap_T::iterator posMaps;
+
+        for ( posMaps = g_context2Map.begin(); posMaps != g_context2Map.end(); ++posMaps )
+        {
+            StringToJExt_T& id2Obj = *posMaps->second;
+            StringToJExt_T::iterator posMap;
+
+            for ( posMap = id2Obj.begin(); posMap != id2Obj.end(); ++posMap )
+            {
+                JSExt* pJSExt = posMap->second;
+
+                if ( pJSExt->CanDelete() )
+                {
+                    delete pJSExt;
+                }
+            }
+
+            id2Obj.erase( id2Obj.begin(), id2Obj.end() );
+        }
+
+        g_context2Map.erase( g_context2Map.begin(), g_context2Map.end() );
+    }
+};
+
+GlobalSharedModule g_sharedModule;
+
+char* g_str2global( const string& strRetVal )
+{
+    int nLen = strRetVal.size();
+
+    if ( nLen >= nMAXSIZE )
+    {
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nLen + 1 ];
+    }
+
+    else
+    {
+        // To minimaize the number of memory reallocations, the assumption
+        // is that in most times this will be the case
+        delete [] g_pszRetVal;
+        g_pszRetVal = new char[ nMAXSIZE ];
+    }
+
+    strcpy( g_pszRetVal, strRetVal.c_str() );
+    return g_pszRetVal;
+}
+
+bool g_unregisterObject( const string& strObjId, void* pContext )
+{
+    // Called by the plugin extension implementation
+    // if the extension handles the deletion of its object
+
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        return false;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+    if ( r == mapID2Obj.end() )
+    {
+        return false;
+    }
+
+    mapID2Obj.erase( strObjId );
+    return true;
+}
+
+char* InvokeFunction( const char* szCommand, void* pContext )
+{
+    StringToJExt_T * pID2Obj = NULL;
+
+    VoidToMap_T::iterator iter = g_context2Map.find( pContext );
+
+    if ( iter != g_context2Map.end() )
+    {
+        pID2Obj = iter->second;
+    }
+    else
+    {
+        pID2Obj = new StringToJExt_T;
+        g_context2Map[ pContext ] = pID2Obj;
+    }
+
+    StringToJExt_T& mapID2Obj = *pID2Obj;
+
+    string strFullCommand = szCommand;
+    vector<string> arParams;
+    g_tokenize( strFullCommand, " ", arParams );
+    string strCommand = arParams[ 0 ];
+    string strRetVal = szERROR;
+
+    if ( strCommand == szCREATE )
+    {
+        string strClassName = arParams[ 1 ];
+        string strObjId = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r != mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Object already exists.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = onCreateObject( strClassName, strObjId );
+
+        if ( pJSExt == NULL )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Unknown object type ";
+            strRetVal += strClassName;
+            return g_str2global( strRetVal );
+        }
+
+        pJSExt->m_pContext = pContext;
+        mapID2Obj[ strObjId ] = pJSExt;
+
+        strRetVal = szOK;
+        strRetVal += strObjId;
+        return g_str2global( strRetVal );
+    }
+    else
+    if ( strCommand == szINVOKE )
+    {
+        string strObjId = arParams[ 1 ];
+        string strMethod = arParams[ 2 ];
+
+        StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+        if ( r == mapID2Obj.end() )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :No object found for id.";
+            return g_str2global( strRetVal );
+        }
+
+        JSExt* pJSExt = r->second;
+
+        size_t nLoc = strFullCommand.find( strObjId );
+
+        if ( nLoc == string::npos )
+        {
+            strRetVal += strObjId;
+            strRetVal += " :Internal InvokeMethod error.";
+            return g_str2global( strRetVal );
+        }
+
+        if ( strMethod == szDISPOSE )
+        {
+            StringToJExt_T::iterator r = mapID2Obj.find( strObjId );
+
+            if ( r == mapID2Obj.end() )
+            {
+                strRetVal = szERROR;
+                strRetVal += strObjId;
+                return g_str2global( strRetVal );
+            }
+
+            JSExt * pJSExt = mapID2Obj[ strObjId ];
+
+            if ( pJSExt->CanDelete() )
+            {
+                delete pJSExt;
+            }
+
+            mapID2Obj.erase( strObjId );
+            strRetVal = szOK;
+            strRetVal += strObjId;
+            return g_str2global( strRetVal );
+        }
+
+        size_t nSuffixLoc = nLoc + strObjId.size();
+        string strInvoke = strFullCommand.substr( nSuffixLoc );
+        strInvoke = g_trim( strInvoke );
+        strRetVal = pJSExt->InvokeMethod( strInvoke );
+        return g_str2global( strRetVal );
+    }
+
+    strRetVal += " :Unknown command ";
+    strRetVal += strCommand;
+    return g_str2global( strRetVal );
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+

+ 70 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/plugin.h

@@ -0,0 +1,70 @@
+#ifndef _PLUGIN_H
+#define _PLUGIN_H
+
+#include <map>
+#include <string>
+#include <vector>
+#include <unistd.h>
+//#include "tokenizer.h"
+
+using namespace std;
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//%% Functions exported by this DLL
+//%% Should always be only SetEventFunc and InvokeFunction
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// g++ requires extern "C" otherwise the names of SetEventFunc and InvokeFunction
+// are mangled C++ style. MS Visual Studio doesn't seem to care though.
+extern "C"
+{
+    typedef void (*SendPluginEv)( const char* szEvent, void* pContext );
+    char* SetEventFunc(SendPluginEv funcPtr);
+    char* InvokeFunction( const char* szCommand, void* pContext );
+}
+
+// JNEXT Framework function of the form:
+// typedef void (*SendPluginEv)( const char* szEvent );
+// used to notify JavaScript of an asynchronous event
+extern SendPluginEv SendPluginEvent;
+
+/////////////////////////////////////////////////////////////////////////
+// Constants and methods common to all JNEXT extensions types
+/////////////////////////////////////////////////////////////////////////
+#define szERROR         "Error "
+#define szOK            "Ok "
+
+#define szDISPOSE       "Dispose"
+#define szINVOKE        "InvokeMethod"
+#define szCREATE        "CreateObj"
+
+/////////////////////////////////////////////////////////////////////////
+// Utility functions
+/////////////////////////////////////////////////////////////////////////
+string& g_trim( string& str );
+void g_tokenize(const string& str,const string& delimiters, vector<string>& tokens);
+char* g_str2static( const string& strRetVal );
+void g_sleep( unsigned int mseconds );
+bool g_unregisterObject( const string& strObjId, void* pContext );
+
+
+/////////////////////////////////////////////////////////////////////////
+// Abstract extension object
+/////////////////////////////////////////////////////////////////////////
+class JSExt
+{
+public:
+    virtual ~JSExt() {};
+    virtual string InvokeMethod( const string& strCommand ) = 0;
+    virtual bool CanDelete( void ) = 0;
+    virtual void TryDelete( void ) {}
+public:
+    void* m_pContext;
+};
+
+/////////////////////////////////////////////////////////////////////////
+// Callback functions to be implemented by the plugin implementation
+/////////////////////////////////////////////////////////////////////////
+extern char* onGetObjList( void );
+extern JSExt* onCreateObject( const string& strClassName, const string& strObjId );
+
+#endif

+ 222 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/tokenizer.cpp

@@ -0,0 +1,222 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+you must not claim that you wrote the original software.
+If you use this software in a product, an acknowledgment
+in the product documentation would be appreciated but is
+not required.
+
+2. Altered source versions must be plainly marked as such,
+and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		Jörg Wiedenmann
+	
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+
+	history:	2006-01-28, Original version
+				2006-03-04, Fixed a small parsing bug, thanks Elias.
+*********************************************************************/
+
+#include "tokenizer.h"
+
+using namespace std;
+
+void tokenize ( const string& str, vector<string>& result,
+			   const string& delimiters, const string& delimiters_preserve,
+			   const string& quote, const string& esc )
+{
+	// clear the vector
+	if ( false == result.empty() )
+	{
+		result.clear();
+	}
+
+	string::size_type pos = 0; // the current position (char) in the string
+	char ch = 0; // buffer for the current character
+	char delimiter = 0;	// the buffer for the delimiter char which
+							// will be added to the tokens if the delimiter
+							// is preserved
+	char current_quote = 0; // the char of the current open quote
+	bool quoted = false; // indicator if there is an open quote
+	string token;  // string buffer for the token
+	bool token_complete = false; // indicates if the current token is
+								 // read to be added to the result vector
+	string::size_type len = str.length();  // length of the input-string
+
+	// for every char in the input-string
+	while ( len > pos )
+	{
+		// get the character of the string and reset the delimiter buffer
+		ch = str.at(pos);
+		delimiter = 0;
+
+		// assume ch isn't a delimiter
+		bool add_char = true;
+
+		// check ...
+
+		// ... if the delimiter is an escaped character
+		bool escaped = false; // indicates if the next char is protected
+		if ( false == esc.empty() ) // check if esc-chars are  provided
+		{
+			if ( string::npos != esc.find_first_of(ch) )
+			{
+				// get the escaped char
+				++pos;
+				if ( pos < len ) // if there are more chars left
+				{
+					// get the next one
+					ch = str.at(pos);
+
+					// add the escaped character to the token
+					add_char = true;
+				}
+				else // cannot get any more characters
+				{
+					// don't add the esc-char
+					add_char = false;
+				}
+
+				// ignore the remaining delimiter checks
+				escaped = true;
+			}
+		}
+
+		// ... if the delimiter is a quote
+		if ( false == quote.empty() && false == escaped )
+		{
+			// if quote chars are provided and the char isn't protected
+			if ( string::npos != quote.find_first_of(ch) )
+			{
+				// if not quoted, set state to open quote and set
+				// the quote character
+				if ( false == quoted )
+				{
+					quoted = true;
+					current_quote = ch;
+
+					// don't add the quote-char to the token
+					add_char = false;
+				}
+				else // if quote is open already
+				{
+					// check if it is the matching character to close it
+					if ( current_quote == ch )
+					{
+						// close quote and reset the quote character
+						quoted = false;
+						current_quote = 0;
+
+						// don't add the quote-char to the token
+						add_char = false;
+					}
+				} // else
+			}
+		}
+
+		// ... if the delimiter isn't preserved
+		if ( false == delimiters.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter is provided and the char isn't protected by
+			// quote or escape char
+			if ( string::npos != delimiters.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+			}
+		}
+
+		// ... if the delimiter is preserved - add it as a token
+		bool add_delimiter = false;
+		if ( false == delimiters_preserve.empty() && false == escaped &&
+			 false == quoted )
+		{
+			// if a delimiter which will be preserved is provided and the
+			// char isn't protected by quote or escape char
+			if ( string::npos != delimiters_preserve.find_first_of(ch) )
+			{
+				// if ch is a delimiter and the token string isn't empty
+				// the token is complete
+				if ( false == token.empty() ) // BUGFIX: 2006-03-04
+				{
+					token_complete = true;
+				}
+
+				// don't add the delimiter to the token
+				add_char = false;
+
+				// add the delimiter
+				delimiter = ch;
+				add_delimiter = true;
+			}
+		}
+
+
+		// add the character to the token
+		if ( true == add_char )
+		{
+			// add the current char
+			token.push_back( ch );
+		}
+
+		// add the token if it is complete
+		if ( true == token_complete && false == token.empty() )
+		{
+			// add the token string
+			result.push_back( token );
+
+			// clear the contents
+			token.clear();
+
+			// build the next token
+			token_complete = false;
+		}
+
+		// add the delimiter
+		if ( true == add_delimiter )
+		{
+			// the next token is the delimiter
+			string delim_token;
+			delim_token.push_back( delimiter );
+			result.push_back( delim_token );
+
+			// REMOVED: 2006-03-04, Bugfix
+		}
+
+		// repeat for the next character
+		++pos;
+	} // while
+
+	// add the final token
+	if ( false == token.empty() )
+	{
+		result.push_back( token );
+	}
+}

+ 55 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/public/tokenizer.h

@@ -0,0 +1,55 @@
+/************************************************************************
+The zlib/libpng License
+
+Copyright (c) 2006 Joerg Wiedenmann
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented;
+	you must not claim that you wrote the original software.
+	If you use this software in a product, an acknowledgment
+	in the product documentation would be appreciated but is
+	not required.
+
+2. Altered source versions must be plainly marked as such,
+	and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+***********************************************************************/
+
+/********************************************************************
+	created:	2006-01-28
+	filename: 	tokenizer.cpp
+	author:		Jörg Wiedenmann
+
+	purpose:	A tokenizer function which provides a very
+				customizable way of breaking up strings.
+*********************************************************************/
+
+#include <vector>
+#include <string>
+using namespace std;
+
+// Function to break up a string into tokens
+//
+// Parameters:
+//-----------
+// str = the input string that will be tokenized
+// result = the tokens for str
+// delimiters = the delimiter characters
+// delimiters preserve = same as above, but the delimiter characters
+//		will be put into the result as a token
+// quote = characters to protect the enclosed characters
+// esc = characters to protect a single character
+//
+
+void tokenize ( const string& str, vector<string>& result,
+			const string& delimiters, const string& delimiters_preserve = "",
+			const string& quote = "\"", const string& esc = "\\" );

binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/libKeyboard.so


binární
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/public/json_reader.o


+ 0 - 0
ionic/plugins/com.ionic.keyboard/src/blackberry10/native/simulator/public/json_value.o


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů