├── LICENSE ├── README.md ├── SCsub ├── android ├── AndroidManifestChunk.xml ├── KeyValDatabase.java ├── KeyValueStorage.java ├── SQLBridge.java └── data │ ├── AESObfuscator.java │ ├── Base64.java │ └── Base64DecoderException.java ├── config.py ├── config.pyc └── res └── values └── strings.xml /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # GodotSQL 3 | 4 | godot sql is a sql bridge for android 5 | 6 | # Usage Api 7 | ``` 8 | 9 | [android] 10 | modules="org/godotengine/godot/SQLBridge" 11 | 12 | var sqlbridge = Globals.get_singleton("SQLBridge") 13 | 14 | sqlbridge.setBool("key", True/False) 15 | sqlbridge.getBool("key") // returns bool 16 | 17 | sqlbridge.setInt("key", Int) 18 | sqlbridge.getInt("key") // returns int 19 | 20 | sqlbridge.setFloat("key", Float) 21 | sqlbridge.getFloat("key") // returns float 22 | 23 | sqlbridge.setValue("key", "value") // set { key = value }. 24 | sqlbridge.getValue("key") // returns String. 25 | 26 | ``` 27 | 28 | # Log events 29 | ``` 30 | adb -d logcat SQLBridge:V DEBUG:V AndroidRuntime:V *:S 31 | ``` 32 | -------------------------------------------------------------------------------- /SCsub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrogSquare/GodotSQL/5950a48d8534023b5cfab9c61eaf18394d237f30/SCsub -------------------------------------------------------------------------------- /android/AndroidManifestChunk.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /android/KeyValDatabase.java: -------------------------------------------------------------------------------- 1 | 2 | package org.godotengine.godot; 3 | 4 | import android.content.ContentValues; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.database.sqlite.SQLiteDatabase; 8 | import android.database.sqlite.SQLiteOpenHelper; 9 | import android.util.Log; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | 15 | public class KeyValDatabase { 16 | 17 | public KeyValDatabase(Context context) { 18 | mDatabaseHelper = new DatabaseHelper(context); 19 | mStoreDB = mDatabaseHelper.getWritableDatabase(); 20 | } 21 | 22 | public synchronized void close() { 23 | mDatabaseHelper.close(); 24 | } 25 | 26 | public void purgeDatabase(Context context) { 27 | context.deleteDatabase(DATABASE_NAME); 28 | } 29 | 30 | public void purgeDatabaseEntries(Context context) { 31 | mStoreDB.delete(KEYVAL_TABLE_NAME, null, null); 32 | } 33 | 34 | public synchronized void setKeyVal(String key, String val) { 35 | ContentValues values = new ContentValues(); 36 | values.put(KEYVAL_COLUMN_VAL, val); 37 | 38 | int affected = mStoreDB.update(KEYVAL_TABLE_NAME, values, KEYVAL_COLUMN_KEY + "='" 39 | + key + "'", null); 40 | 41 | if (affected == 0) { 42 | values.put(KEYVAL_COLUMN_KEY, key); 43 | mStoreDB.replace(KEYVAL_TABLE_NAME, null, values); 44 | } 45 | } 46 | 47 | public synchronized String getKeyVal(String key) { 48 | Cursor cursor = mStoreDB.query(KEYVAL_TABLE_NAME, KEYVAL_COLUMNS, 49 | KEYVAL_COLUMN_KEY + "='" + key + "'", null, null, null, null); 50 | 51 | if (cursor != null && cursor.moveToNext()) { 52 | int valColIdx = cursor.getColumnIndexOrThrow(KEYVAL_COLUMN_VAL); 53 | String ret = cursor.getString(valColIdx); 54 | cursor.close(); 55 | return ret; 56 | } else { Log.i(TAG, "return Null.!"); } 57 | 58 | if(cursor != null) { cursor.close(); } 59 | 60 | return null; 61 | } 62 | 63 | public synchronized void deleteKeyVal(String key) { 64 | mStoreDB.delete(KEYVAL_TABLE_NAME, KEYVAL_COLUMN_KEY + "=?", new String[] { key }); 65 | } 66 | 67 | public synchronized HashMap getQueryVals(String query) { 68 | query = query.replace('*', '%'); 69 | Cursor cursor = mStoreDB.query(KEYVAL_TABLE_NAME, KEYVAL_COLUMNS, KEYVAL_COLUMN_KEY 70 | + " LIKE '" + query + "'", 71 | null, null, null, null); 72 | 73 | HashMap ret = new HashMap(); 74 | while (cursor != null && cursor.moveToNext()) { 75 | try { 76 | int valColIdx = cursor.getColumnIndexOrThrow(KEYVAL_COLUMN_VAL); 77 | int keyColIdx = cursor.getColumnIndexOrThrow(KEYVAL_COLUMN_KEY); 78 | ret.put(cursor.getString(keyColIdx), cursor.getString(valColIdx)); 79 | } catch (IllegalArgumentException exx) { } 80 | } 81 | 82 | if(cursor != null) { cursor.close(); } 83 | 84 | return ret; 85 | } 86 | 87 | public synchronized String getQueryOne(String query) { 88 | query = query.replace('*', '%'); 89 | Cursor cursor = mStoreDB.query(KEYVAL_TABLE_NAME, KEYVAL_COLUMNS, KEYVAL_COLUMN_KEY 90 | + " LIKE '" + query + "'", 91 | null, null, null, null, "1"); 92 | 93 | if(cursor != null) { 94 | boolean moved = cursor.moveToFirst(); 95 | if (moved) { 96 | int valColIdx = cursor.getColumnIndexOrThrow(KEYVAL_COLUMN_VAL); 97 | String ret = cursor.getString(valColIdx); 98 | 99 | cursor.close(); 100 | 101 | return ret; 102 | } 103 | } 104 | 105 | return null; 106 | } 107 | 108 | public synchronized int getQueryCount(String query) { 109 | query = query.replace('*', '%'); 110 | Cursor cursor = mStoreDB.rawQuery("SELECT COUNT(" + KEYVAL_COLUMN_VAL + ") from " + 111 | KEYVAL_TABLE_NAME + " WHERE " + KEYVAL_COLUMN_KEY + " LIKE '" + query +"'", null); 112 | 113 | if(cursor != null) { 114 | boolean moved = cursor.moveToFirst(); 115 | 116 | if (moved) { 117 | int count = cursor.getInt(0); 118 | cursor.close(); 119 | 120 | return count; 121 | } 122 | } 123 | 124 | return 0; 125 | } 126 | 127 | public synchronized List getAllKeys() { 128 | Cursor cursor = mStoreDB.query(KEYVAL_TABLE_NAME, new String[] { KEYVAL_COLUMN_KEY }, 129 | null, null, null, null, null); 130 | 131 | List ret = new ArrayList(); 132 | while (cursor != null && cursor.moveToNext()) { 133 | 134 | try { 135 | int keyColIdx = cursor.getColumnIndexOrThrow(KEYVAL_COLUMN_KEY); 136 | ret.add(cursor.getString(keyColIdx)); 137 | } catch (IllegalArgumentException exx) { } 138 | } 139 | 140 | if(cursor != null) { cursor.close(); } 141 | 142 | return ret; 143 | } 144 | 145 | private class DatabaseHelper extends SQLiteOpenHelper { 146 | 147 | public DatabaseHelper(Context context) { 148 | super(context, DATABASE_NAME, null, 1); 149 | } 150 | 151 | @Override 152 | public void onCreate(SQLiteDatabase sqLiteDatabase) { 153 | if (!sqLiteDatabase.isReadOnly()){ 154 | sqLiteDatabase.execSQL("PRAGMA foreign_key=ON"); 155 | } 156 | 157 | // sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS " + 158 | // KEYVAL_TABLE_NAME + "(" + KEYVAL_COLUMN_KEY + " TEXT PRIMARY KEY, " + 159 | // KEYVAL_COLUMN_VAL + " TEXT)"); 160 | 161 | sqLiteDatabase.execSQL(CREATE_TABLE_KEYVAL); 162 | } 163 | 164 | @Override 165 | public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { 166 | // Nothing to do here ... 167 | } 168 | 169 | } 170 | 171 | private static final String KEYVAL_TABLE_NAME = "kv_store"; 172 | public static final String KEYVAL_COLUMN_KEY = "key"; 173 | public static final String KEYVAL_COLUMN_VAL = "val"; 174 | 175 | public static final String CREATE_TABLE_KEYVAL = "CREATE TABLE IF NOT EXISTS " 176 | + KEYVAL_TABLE_NAME + "(" + KEYVAL_COLUMN_KEY + " TEXT PRIMARY KEY, " 177 | + KEYVAL_COLUMN_VAL + " TEXT)"; 178 | 179 | private static final String[] KEYVAL_COLUMNS = { KEYVAL_COLUMN_KEY, KEYVAL_COLUMN_VAL }; 180 | 181 | private static final String TAG = "SQLBridge"; 182 | private static final String DATABASE_NAME = "godot.kv.db.custom"; 183 | private SQLiteDatabase mStoreDB; 184 | private DatabaseHelper mDatabaseHelper; 185 | } 186 | -------------------------------------------------------------------------------- /android/KeyValueStorage.java: -------------------------------------------------------------------------------- 1 | 2 | package org.godotengine.godot; 3 | 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.text.TextUtils; 7 | import android.util.Log; 8 | import android.provider.Settings; 9 | 10 | import java.security.MessageDigest; 11 | import java.security.NoSuchAlgorithmException; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Locale; 17 | 18 | import org.godotengine.godot.data.AESObfuscator; 19 | import org.godotengine.godot.data.Base64; 20 | import org.godotengine.godot.data.Base64DecoderException; 21 | 22 | import java.sql.Timestamp; 23 | 24 | public class KeyValueStorage { 25 | 26 | public static void set_context(Context act) { 27 | context = act; 28 | } 29 | 30 | private static String getDeviceId() { 31 | String android_id = Settings.Secure.getString( 32 | context.getContentResolver(), Settings.Secure.ANDROID_ID); 33 | 34 | if (android_id == null) { 35 | android_id = "GODOT_FAKE_ID"; 36 | } 37 | 38 | //String deviceId = md5(android_id).toUpperCase(Locale.US); 39 | return android_id; 40 | } 41 | 42 | public static String getValue(String key) { 43 | Log.d(TAG, "Fetching value for " + key); 44 | 45 | key = getAESObfuscator().obfuscateString(key); 46 | String val = getDatabase().getKeyVal(key); 47 | 48 | if (val != null && !TextUtils.isEmpty(val)) { 49 | try { 50 | val = getAESObfuscator().unobfuscateToString(val); 51 | } catch (AESObfuscator.ValidationException e) { 52 | Log.e(TAG, e.getMessage()); 53 | val = "0"; 54 | } 55 | 56 | Log.d(TAG, "The fetched value is " + val); 57 | } else { val = "0"; } 58 | 59 | return val; 60 | } 61 | 62 | public static void setNonEncryptedKeyValue(String key, String val) { 63 | Log.d(TAG, "Setting " + val + " for key: " + key); 64 | 65 | if (val.equals("false")) { val = "0"; } 66 | else if (val.equals("true")) { val = "1"; } 67 | 68 | val = getAESObfuscator().obfuscateString(val); 69 | 70 | getDatabase().setKeyVal(key, val); 71 | } 72 | 73 | public static void deleteNonEncryptedKeyValue(String key) { 74 | Log.d(TAG, "Deleting " + key); 75 | 76 | getDatabase().deleteKeyVal(key); 77 | } 78 | 79 | public static String getNonEncryptedKeyValue(String key) { 80 | Log.d(TAG, "Fetching value for " + key); 81 | 82 | String val = getDatabase().getKeyVal(key); 83 | 84 | if (val != null && !TextUtils.isEmpty(val)) { 85 | try { 86 | val = getAESObfuscator().unobfuscateToString(val); 87 | } catch (AESObfuscator.ValidationException e) { 88 | Log.e(TAG, e.getMessage()); 89 | val = "0"; 90 | } 91 | 92 | Log.d(TAG, "The fetched value is " + val); 93 | } else { val = "0"; } 94 | 95 | return val; 96 | } 97 | 98 | public static HashMap getNonEncryptedQueryValues(String query) { 99 | HashMap vals = getDatabase().getQueryVals(query); 100 | HashMap results = new HashMap(); 101 | 102 | for(String key : vals.keySet()) { 103 | String val = vals.get(key); 104 | 105 | if (val != null && !TextUtils.isEmpty(val)) { 106 | try { 107 | val = getAESObfuscator().unobfuscateToString(val); 108 | results.put(key, val); 109 | } catch (AESObfuscator.ValidationException e) { 110 | Log.e(TAG, e.getMessage()); 111 | } 112 | } 113 | } 114 | 115 | Log.d(TAG, "Fetched " + results.size() + " results"); 116 | 117 | return results; 118 | } 119 | 120 | public static String getOneForNonEncryptedQuery(String query) { 121 | String val = getDatabase().getQueryOne(query); 122 | if (val != null && !TextUtils.isEmpty(val)) { 123 | try { 124 | val = getAESObfuscator().unobfuscateToString(val); 125 | return val; 126 | } catch (AESObfuscator.ValidationException e) { 127 | Log.e(TAG, e.getMessage()); 128 | } 129 | } 130 | return null; 131 | } 132 | 133 | public static int getCountForNonEncryptedQuery(String query) { 134 | return getDatabase().getQueryCount(query); 135 | } 136 | 137 | public static List getEncryptedKeys() { 138 | List encryptedKeys = getDatabase().getAllKeys(); 139 | List resultKeys = new ArrayList(); 140 | 141 | for (String encryptedKey : encryptedKeys) { 142 | try { 143 | String unencryptedKey = 144 | getAESObfuscator().unobfuscateToString(encryptedKey); 145 | resultKeys.add(unencryptedKey); 146 | } catch (AESObfuscator.ValidationException e) { 147 | Log.d(TAG, e.getMessage()); 148 | } catch (RuntimeException e) { 149 | Log.e(TAG, e.getMessage()); 150 | } 151 | } 152 | 153 | return resultKeys; 154 | } 155 | 156 | public static void setValue(String key, String val) { 157 | Log.d(TAG, "Setting " + val + " for key: " + key); 158 | 159 | if (val.equals("false")) { val = "0"; } 160 | else if (val.equals("true")) { val = "1"; } 161 | 162 | key = getAESObfuscator().obfuscateString(key); 163 | val = getAESObfuscator().obfuscateString(val); 164 | 165 | getDatabase().setKeyVal(key, val); 166 | } 167 | 168 | public static void deleteKeyValue(String key) { 169 | Log.d(TAG, "Deleting " + key); 170 | 171 | key = getAESObfuscator().obfuscateString(key); 172 | 173 | getDatabase().deleteKeyVal(key); 174 | } 175 | 176 | public static void purge() { 177 | Log.d(TAG, "Purging database"); 178 | 179 | getDatabase().purgeDatabaseEntries(context); 180 | } 181 | 182 | private static synchronized KeyValDatabase getDatabase() { 183 | if (mKvDatabase == null) { 184 | mKvDatabase = new KeyValDatabase(context); 185 | } 186 | 187 | return mKvDatabase; 188 | } 189 | 190 | private static AESObfuscator getAESObfuscator() { 191 | if (mObfuscator == null) { 192 | mObfuscator = new AESObfuscator( 193 | obfuscationSalt, context.getPackageName(), getDeviceId()); 194 | } 195 | 196 | return mObfuscator; 197 | } 198 | 199 | private static final String TAG = "SQLBridge"; 200 | 201 | public static final byte[] obfuscationSalt = 202 | new byte[] { 64, -24, -123, -57, 38, -52, 87, -112, -65, -117, 89, 51, -113, -35, 30, 57, -55, 203 | 75, -26, 4 }; 204 | 205 | private static AESObfuscator mObfuscator; 206 | private static KeyValDatabase mKvDatabase; 207 | 208 | private static Context context; 209 | private static String package_name; 210 | } 211 | -------------------------------------------------------------------------------- /android/SQLBridge.java: -------------------------------------------------------------------------------- 1 | 2 | package org.godotengine.godot; 3 | 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.os.Bundle; 9 | import android.content.Intent; 10 | 11 | import com.godot.game.BuildConfig; 12 | 13 | public class SQLBridge extends Godot.SingletonBase { 14 | 15 | protected void onMainActivityResult (int requestCode, int resultCode, Intent data) { } 16 | 17 | protected void onMainPause () { } 18 | protected void onMainResume () { } 19 | protected void onMainDestroy () { } 20 | 21 | // singletons will always miss first onGLSurfaceChanged call 22 | //protected void onGLSurfaceChanged (GL10 gl, int width, int height) { } 23 | //protected void onGLDrawFrame (GL10 gl) { } 24 | 25 | static public Godot.SingletonBase initialize (Activity p_activity) { 26 | return new SQLBridge(p_activity); 27 | } 28 | 29 | public SQLBridge (Activity p_activity) { 30 | registerClass ("SQLBridge", new String[] { 31 | "setValue", "setInt", "setFloat", "setBool", 32 | "getValue", "getInt", "getFloat", "getBool"}); 33 | 34 | activity = p_activity; 35 | KeyValueStorage.set_context(activity.getApplicationContext()); 36 | 37 | Log.d("godot", "SQLBridge:Initialized"); 38 | } 39 | 40 | public void setInt(String key, int value) { 41 | if (BuildConfig.DEBUG) { Log.d(TAG, "Setting Int: {" + key + ":" + value + "}"); } 42 | 43 | KeyValueStorage.setValue(key, Integer.toString(value)); 44 | } 45 | 46 | public void setFloat(String key, float value) { 47 | if (BuildConfig.DEBUG) { Log.d(TAG, "Setting Float: {" + key + ":" + value + "}"); } 48 | 49 | KeyValueStorage.setValue(key, Float.toString(value)); 50 | } 51 | 52 | public void setBool(String key, boolean value) { 53 | if (BuildConfig.DEBUG) { Log.d(TAG, "Setting Bool: {" + key + ":" + value + "}"); } 54 | 55 | KeyValueStorage.setValue(key, Boolean.toString(value)); 56 | } 57 | 58 | public void setValue(String key, String value) { 59 | if (BuildConfig.DEBUG) { Log.d(TAG, "Setting String: {" + key + ":" + value + "}"); } 60 | 61 | KeyValueStorage.setValue(key, value); 62 | } 63 | 64 | public int getInt(String key) { 65 | if (BuildConfig.DEBUG) { Log.d(TAG, "Getting Int: " + key); } 66 | 67 | return Integer.valueOf(KeyValueStorage.getValue(key)); 68 | } 69 | 70 | public float getFloat(String key) { 71 | if (BuildConfig.DEBUG) { Log.d(TAG, "Getting Float: " + key); } 72 | 73 | return Float.valueOf(KeyValueStorage.getValue(key)); 74 | } 75 | 76 | public boolean getBool(String key) { 77 | if (BuildConfig.DEBUG) { Log.d(TAG, "Getting Bool: " + key); } 78 | 79 | return Boolean.valueOf(KeyValueStorage.getValue(key)); 80 | } 81 | 82 | public String getValue(String key) { 83 | if (BuildConfig.DEBUG) { Log.d(TAG, "Getting IString: " + key); } 84 | 85 | return KeyValueStorage.getValue(key); 86 | } 87 | 88 | private static Activity activity; 89 | private static final String TAG = "SQLBridge"; 90 | } 91 | -------------------------------------------------------------------------------- /android/data/AESObfuscator.java: -------------------------------------------------------------------------------- 1 | 2 | package org.godotengine.godot.data; 3 | 4 | import android.text.TextUtils; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.security.GeneralSecurityException; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.security.spec.KeySpec; 11 | 12 | import javax.crypto.BadPaddingException; 13 | import javax.crypto.Cipher; 14 | import javax.crypto.IllegalBlockSizeException; 15 | import javax.crypto.SecretKey; 16 | import javax.crypto.SecretKeyFactory; 17 | import javax.crypto.spec.IvParameterSpec; 18 | import javax.crypto.spec.PBEKeySpec; 19 | import javax.crypto.spec.SecretKeySpec; 20 | 21 | public class AESObfuscator { 22 | private static final String SECRET = "njkcndwiu63fjnp9"; 23 | 24 | private static final String UTF8 = "UTF-8"; 25 | private static final String KEYGEN_ALGORITHM = "PBEWITHSHAAND256BITAES-CBC-BC"; 26 | private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; 27 | private static final byte[] IV = 28 | { 16, 74, 71, -80, 32, 101, -47, 72, 117, -14, 0, -29, 70, 65, -12, 74 }; 29 | 30 | private static final String header = "AESObfuscator-1|"; 31 | 32 | private Cipher mEncryptor; 33 | private Cipher mDecryptor; 34 | 35 | public AESObfuscator(byte[] salt, String applicationId, String deviceId) { 36 | byte[] passwordData = null; 37 | 38 | String sec = SECRET; 39 | try { 40 | SecretKeyFactory factory = SecretKeyFactory.getInstance(KEYGEN_ALGORITHM); 41 | KeySpec keySpec = 42 | new PBEKeySpec((applicationId + deviceId + sec).toCharArray(), salt, 1024, 256); 43 | 44 | passwordData = factory.generateSecret(keySpec).getEncoded(); 45 | } 46 | catch (GeneralSecurityException e) { 47 | // MJackUtils.LogDebug("Probably an incompatible device. Trying different approach."); 48 | 49 | MessageDigest digester = null; 50 | try { 51 | digester = MessageDigest.getInstance("MD5"); 52 | char[] password = (applicationId + deviceId + sec).toCharArray(); 53 | 54 | for (int i = 0; i < password.length; i++) { 55 | digester.update((byte) password[i]); 56 | } 57 | 58 | passwordData = digester.digest(); 59 | } 60 | catch (NoSuchAlgorithmException e1) { 61 | throw new RuntimeException("Invalid environment", e1); 62 | } 63 | } 64 | 65 | SecretKey secret = new SecretKeySpec(passwordData, "AES"); 66 | try { 67 | mEncryptor = Cipher.getInstance(CIPHER_ALGORITHM); 68 | mEncryptor.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(IV)); 69 | 70 | mDecryptor = Cipher.getInstance(CIPHER_ALGORITHM); 71 | mDecryptor.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(IV)); 72 | } 73 | catch (GeneralSecurityException e) { 74 | throw new RuntimeException("Invalid environment 2", e); 75 | } 76 | 77 | } 78 | 79 | public String obfuscateInt(int original) { 80 | return obfuscateString("" + original); 81 | } 82 | 83 | public synchronized String obfuscateString(String original) { 84 | if (TextUtils.isEmpty(original)) { return original; } 85 | 86 | try { 87 | return Base64.encode(mEncryptor.doFinal((header + original).getBytes(UTF8))); 88 | } 89 | catch (UnsupportedEncodingException e) { 90 | throw new RuntimeException("Invalid environment", e); 91 | } 92 | catch (GeneralSecurityException e) { 93 | throw new RuntimeException("Invalid environment", e); 94 | } 95 | } 96 | 97 | public int unobfuscateToInt(String obfuscated) throws ValidationException { 98 | return Integer.parseInt(unobfuscateToString(obfuscated)); 99 | } 100 | 101 | public synchronized String unobfuscateToString(String obfuscated) throws ValidationException { 102 | if (TextUtils.isEmpty(obfuscated)) { return null; } 103 | 104 | try { 105 | String result = new String(mDecryptor.doFinal(Base64.decode(obfuscated)), UTF8); 106 | 107 | int headerIndex = result.indexOf(header); 108 | if (headerIndex != 0) { 109 | throw new ValidationException("Header not found (invalid data or key)" + ":" + 110 | obfuscated); 111 | } 112 | 113 | return result.substring(header.length(), result.length()); 114 | } 115 | catch (Base64DecoderException e) { 116 | throw new ValidationException(e.getMessage() + ":" + obfuscated); 117 | } 118 | catch (IllegalBlockSizeException e) { 119 | throw new ValidationException(e.getMessage() + ":" + obfuscated); 120 | } 121 | catch (BadPaddingException e) { 122 | throw new ValidationException(e.getMessage() + ":" + obfuscated); 123 | } 124 | catch (UnsupportedEncodingException e) { 125 | throw new RuntimeException("Invalid environment", e); 126 | } 127 | } 128 | 129 | public class ValidationException extends Exception { 130 | public ValidationException() { 131 | super(); 132 | } 133 | 134 | public ValidationException(String s) { 135 | super(s); 136 | } 137 | 138 | private static final long serialVersionUID = 1L; 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /android/data/Base64.java: -------------------------------------------------------------------------------- 1 | // Portions copyright 2002, Google, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package org.godotengine.godot.data; 16 | 17 | // This code was converted from code at http://iharder.sourceforge.net/base64/ 18 | // Lots of extraneous features were removed. 19 | /* The original code said: 20 | *

21 | * I am placing this code in the Public Domain. Do with it as you will. 22 | * This software comes with no guarantees or warranties but with 23 | * plenty of well-wishing instead! 24 | * Please visit 25 | * http://iharder.net/xmlizable 26 | * periodically to check for updates or to contribute improvements. 27 | *

28 | * 29 | * @author Robert Harder 30 | * @author rharder@usa.net 31 | * @version 1.3 32 | */ 33 | 34 | /** 35 | * Base64 converter class. This code is not a complete MIME encoder; 36 | * it simply converts binary data to base64 data and back. 37 | * 38 | *

Note {@link CharBase64} is a GWT-compatible implementation of this 39 | * class. 40 | */ 41 | public class Base64 { 42 | /** Specify encoding (value is {@code true}). */ 43 | public final static boolean ENCODE = true; 44 | 45 | /** Specify decoding (value is {@code false}). */ 46 | public final static boolean DECODE = false; 47 | 48 | /** The equals sign (=) as a byte. */ 49 | private final static byte EQUALS_SIGN = (byte) '='; 50 | 51 | /** The new line character (\n) as a byte. */ 52 | private final static byte NEW_LINE = (byte) '\n'; 53 | 54 | /** 55 | * The 64 valid Base64 values. 56 | */ 57 | private final static byte[] ALPHABET = 58 | {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', 59 | (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', 60 | (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', 61 | (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', 62 | (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', 63 | (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', 64 | (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', 65 | (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', 66 | (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', 67 | (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', 68 | (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', 69 | (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', 70 | (byte) '9', (byte) '+', (byte) '/'}; 71 | 72 | /** 73 | * The 64 valid web safe Base64 values. 74 | */ 75 | private final static byte[] WEBSAFE_ALPHABET = 76 | {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', 77 | (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', 78 | (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', 79 | (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', 80 | (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', 81 | (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', 82 | (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', 83 | (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', 84 | (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', 85 | (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', 86 | (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', 87 | (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', 88 | (byte) '9', (byte) '-', (byte) '_'}; 89 | 90 | /** 91 | * Translates a Base64 value to either its 6-bit reconstruction value 92 | * or a negative number indicating some other meaning. 93 | **/ 94 | private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 95 | -5, -5, // Whitespace: Tab and Linefeed 96 | -9, -9, // Decimal 11 - 12 97 | -5, // Whitespace: Carriage Return 98 | -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 99 | -9, -9, -9, -9, -9, // Decimal 27 - 31 100 | -5, // Whitespace: Space 101 | -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 102 | 62, // Plus sign at decimal 43 103 | -9, -9, -9, // Decimal 44 - 46 104 | 63, // Slash at decimal 47 105 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine 106 | -9, -9, -9, // Decimal 58 - 60 107 | -1, // Equals sign at decimal 61 108 | -9, -9, -9, // Decimal 62 - 64 109 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' 110 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' 111 | -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 112 | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' 113 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' 114 | -9, -9, -9, -9, -9 // Decimal 123 - 127 115 | /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 116 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 117 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 118 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 119 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 120 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 121 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 122 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 123 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 124 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ 125 | }; 126 | 127 | /** The web safe decodabet */ 128 | private final static byte[] WEBSAFE_DECODABET = 129 | {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 130 | -5, -5, // Whitespace: Tab and Linefeed 131 | -9, -9, // Decimal 11 - 12 132 | -5, // Whitespace: Carriage Return 133 | -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 134 | -9, -9, -9, -9, -9, // Decimal 27 - 31 135 | -5, // Whitespace: Space 136 | -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44 137 | 62, // Dash '-' sign at decimal 45 138 | -9, -9, // Decimal 46-47 139 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine 140 | -9, -9, -9, // Decimal 58 - 60 141 | -1, // Equals sign at decimal 61 142 | -9, -9, -9, // Decimal 62 - 64 143 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' 144 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' 145 | -9, -9, -9, -9, // Decimal 91-94 146 | 63, // Underscore '_' at decimal 95 147 | -9, // Decimal 96 148 | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' 149 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' 150 | -9, -9, -9, -9, -9 // Decimal 123 - 127 151 | /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 152 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 153 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 154 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 155 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 156 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 157 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 158 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 159 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 160 | -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */ 161 | }; 162 | 163 | // Indicates white space in encoding 164 | private final static byte WHITE_SPACE_ENC = -5; 165 | // Indicates equals sign in encoding 166 | private final static byte EQUALS_SIGN_ENC = -1; 167 | 168 | /** Defeats instantiation. */ 169 | private Base64() { 170 | } 171 | 172 | /* ******** E N C O D I N G M E T H O D S ******** */ 173 | 174 | /** 175 | * Encodes up to three bytes of the array source 176 | * and writes the resulting four Base64 bytes to destination. 177 | * The source and destination arrays can be manipulated 178 | * anywhere along their length by specifying 179 | * srcOffset and destOffset. 180 | * This method does not check to make sure your arrays 181 | * are large enough to accommodate srcOffset + 3 for 182 | * the source array or destOffset + 4 for 183 | * the destination array. 184 | * The actual number of significant bytes in your array is 185 | * given by numSigBytes. 186 | * 187 | * @param source the array to convert 188 | * @param srcOffset the index where conversion begins 189 | * @param numSigBytes the number of significant bytes in your array 190 | * @param destination the array to hold the conversion 191 | * @param destOffset the index where output will be put 192 | * @param alphabet is the encoding alphabet 193 | * @return the destination array 194 | * @since 1.3 195 | */ 196 | private static byte[] encode3to4(byte[] source, int srcOffset, 197 | int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) { 198 | // 1 2 3 199 | // 01234567890123456789012345678901 Bit position 200 | // --------000000001111111122222222 Array position from threeBytes 201 | // --------| || || || | Six bit groups to index alphabet 202 | // >>18 >>12 >> 6 >> 0 Right shift necessary 203 | // 0x3f 0x3f 0x3f Additional AND 204 | 205 | // Create buffer with zero-padding if there are only one or two 206 | // significant bytes passed in the array. 207 | // We have to shift left 24 in order to flush out the 1's that appear 208 | // when Java treats a value as negative that is cast from a byte to an int. 209 | int inBuff = 210 | (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) 211 | | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) 212 | | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); 213 | 214 | switch (numSigBytes) { 215 | case 3: 216 | destination[destOffset] = alphabet[(inBuff >>> 18)]; 217 | destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; 218 | destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; 219 | destination[destOffset + 3] = alphabet[(inBuff) & 0x3f]; 220 | return destination; 221 | case 2: 222 | destination[destOffset] = alphabet[(inBuff >>> 18)]; 223 | destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; 224 | destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f]; 225 | destination[destOffset + 3] = EQUALS_SIGN; 226 | return destination; 227 | case 1: 228 | destination[destOffset] = alphabet[(inBuff >>> 18)]; 229 | destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f]; 230 | destination[destOffset + 2] = EQUALS_SIGN; 231 | destination[destOffset + 3] = EQUALS_SIGN; 232 | return destination; 233 | default: 234 | return destination; 235 | } // end switch 236 | } // end encode3to4 237 | 238 | /** 239 | * Encodes a byte array into Base64 notation. 240 | * Equivalent to calling 241 | * {@code encodeBytes(source, 0, source.length)} 242 | * 243 | * @param source The data to convert 244 | * @since 1.4 245 | */ 246 | public static String encode(byte[] source) { 247 | return encode(source, 0, source.length, ALPHABET, true); 248 | } 249 | 250 | /** 251 | * Encodes a byte array into web safe Base64 notation. 252 | * 253 | * @param source The data to convert 254 | * @param doPadding is {@code true} to pad result with '=' chars 255 | * if it does not fall on 3 byte boundaries 256 | */ 257 | public static String encodeWebSafe(byte[] source, boolean doPadding) { 258 | return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding); 259 | } 260 | 261 | /** 262 | * Encodes a byte array into Base64 notation. 263 | * 264 | * @param source the data to convert 265 | * @param off offset in array where conversion should begin 266 | * @param len length of data to convert 267 | * @param alphabet the encoding alphabet 268 | * @param doPadding is {@code true} to pad result with '=' chars 269 | * if it does not fall on 3 byte boundaries 270 | * @since 1.4 271 | */ 272 | public static String encode(byte[] source, int off, int len, byte[] alphabet, 273 | boolean doPadding) { 274 | byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE); 275 | int outLen = outBuff.length; 276 | 277 | // If doPadding is false, set length to truncate '=' 278 | // padding characters 279 | while (doPadding == false && outLen > 0) { 280 | if (outBuff[outLen - 1] != '=') { 281 | break; 282 | } 283 | outLen -= 1; 284 | } 285 | 286 | return new String(outBuff, 0, outLen); 287 | } 288 | 289 | /** 290 | * Encodes a byte array into Base64 notation. 291 | * 292 | * @param source the data to convert 293 | * @param off offset in array where conversion should begin 294 | * @param len length of data to convert 295 | * @param alphabet is the encoding alphabet 296 | * @param maxLineLength maximum length of one line. 297 | * @return the BASE64-encoded byte array 298 | */ 299 | public static byte[] encode(byte[] source, int off, int len, byte[] alphabet, 300 | int maxLineLength) { 301 | int lenDiv3 = (len + 2) / 3; // ceil(len / 3) 302 | int len43 = lenDiv3 * 4; 303 | byte[] outBuff = new byte[len43 // Main 4:3 304 | + (len43 / maxLineLength)]; // New lines 305 | 306 | int d = 0; 307 | int e = 0; 308 | int len2 = len - 2; 309 | int lineLength = 0; 310 | for (; d < len2; d += 3, e += 4) { 311 | 312 | // The following block of code is the same as 313 | // encode3to4( source, d + off, 3, outBuff, e, alphabet ); 314 | // but inlined for faster encoding (~20% improvement) 315 | int inBuff = 316 | ((source[d + off] << 24) >>> 8) 317 | | ((source[d + 1 + off] << 24) >>> 16) 318 | | ((source[d + 2 + off] << 24) >>> 24); 319 | outBuff[e] = alphabet[(inBuff >>> 18)]; 320 | outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f]; 321 | outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f]; 322 | outBuff[e + 3] = alphabet[(inBuff) & 0x3f]; 323 | 324 | lineLength += 4; 325 | if (lineLength == maxLineLength) { 326 | outBuff[e + 4] = NEW_LINE; 327 | e++; 328 | lineLength = 0; 329 | } // end if: end of line 330 | } // end for: each piece of array 331 | 332 | if (d < len) { 333 | encode3to4(source, d + off, len - d, outBuff, e, alphabet); 334 | 335 | lineLength += 4; 336 | if (lineLength == maxLineLength) { 337 | // Add a last newline 338 | outBuff[e + 4] = NEW_LINE; 339 | e++; 340 | } 341 | e += 4; 342 | } 343 | 344 | assert (e == outBuff.length); 345 | return outBuff; 346 | } 347 | 348 | 349 | /* ******** D E C O D I N G M E T H O D S ******** */ 350 | 351 | 352 | /** 353 | * Decodes four bytes from array source 354 | * and writes the resulting bytes (up to three of them) 355 | * to destination. 356 | * The source and destination arrays can be manipulated 357 | * anywhere along their length by specifying 358 | * srcOffset and destOffset. 359 | * This method does not check to make sure your arrays 360 | * are large enough to accommodate srcOffset + 4 for 361 | * the source array or destOffset + 3 for 362 | * the destination array. 363 | * This method returns the actual number of bytes that 364 | * were converted from the Base64 encoding. 365 | * 366 | * 367 | * @param source the array to convert 368 | * @param srcOffset the index where conversion begins 369 | * @param destination the array to hold the conversion 370 | * @param destOffset the index where output will be put 371 | * @param decodabet the decodabet for decoding Base64 content 372 | * @return the number of decoded bytes converted 373 | * @since 1.3 374 | */ 375 | private static int decode4to3(byte[] source, int srcOffset, 376 | byte[] destination, int destOffset, byte[] decodabet) { 377 | // Example: Dk== 378 | if (source[srcOffset + 2] == EQUALS_SIGN) { 379 | int outBuff = 380 | ((decodabet[source[srcOffset]] << 24) >>> 6) 381 | | ((decodabet[source[srcOffset + 1]] << 24) >>> 12); 382 | 383 | destination[destOffset] = (byte) (outBuff >>> 16); 384 | return 1; 385 | } else if (source[srcOffset + 3] == EQUALS_SIGN) { 386 | // Example: DkL= 387 | int outBuff = 388 | ((decodabet[source[srcOffset]] << 24) >>> 6) 389 | | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) 390 | | ((decodabet[source[srcOffset + 2]] << 24) >>> 18); 391 | 392 | destination[destOffset] = (byte) (outBuff >>> 16); 393 | destination[destOffset + 1] = (byte) (outBuff >>> 8); 394 | return 2; 395 | } else { 396 | // Example: DkLE 397 | int outBuff = 398 | ((decodabet[source[srcOffset]] << 24) >>> 6) 399 | | ((decodabet[source[srcOffset + 1]] << 24) >>> 12) 400 | | ((decodabet[source[srcOffset + 2]] << 24) >>> 18) 401 | | ((decodabet[source[srcOffset + 3]] << 24) >>> 24); 402 | 403 | destination[destOffset] = (byte) (outBuff >> 16); 404 | destination[destOffset + 1] = (byte) (outBuff >> 8); 405 | destination[destOffset + 2] = (byte) (outBuff); 406 | return 3; 407 | } 408 | } // end decodeToBytes 409 | 410 | 411 | /** 412 | * Decodes data from Base64 notation. 413 | * 414 | * @param s the string to decode (decoded in default encoding) 415 | * @return the decoded data 416 | * @since 1.4 417 | */ 418 | public static byte[] decode(String s) throws Base64DecoderException { 419 | byte[] bytes = s.getBytes(); 420 | return decode(bytes, 0, bytes.length); 421 | } 422 | 423 | /** 424 | * Decodes data from web safe Base64 notation. 425 | * Web safe encoding uses '-' instead of '+', '_' instead of '/' 426 | * 427 | * @param s the string to decode (decoded in default encoding) 428 | * @return the decoded data 429 | */ 430 | public static byte[] decodeWebSafe(String s) throws Base64DecoderException { 431 | byte[] bytes = s.getBytes(); 432 | return decodeWebSafe(bytes, 0, bytes.length); 433 | } 434 | 435 | /** 436 | * Decodes Base64 content in byte array format and returns 437 | * the decoded byte array. 438 | * 439 | * @param source The Base64 encoded data 440 | * @return decoded data 441 | * @since 1.3 442 | * @throws Base64DecoderException 443 | */ 444 | public static byte[] decode(byte[] source) throws Base64DecoderException { 445 | return decode(source, 0, source.length); 446 | } 447 | 448 | /** 449 | * Decodes web safe Base64 content in byte array format and returns 450 | * the decoded data. 451 | * Web safe encoding uses '-' instead of '+', '_' instead of '/' 452 | * 453 | * @param source the string to decode (decoded in default encoding) 454 | * @return the decoded data 455 | */ 456 | public static byte[] decodeWebSafe(byte[] source) 457 | throws Base64DecoderException { 458 | return decodeWebSafe(source, 0, source.length); 459 | } 460 | 461 | /** 462 | * Decodes Base64 content in byte array format and returns 463 | * the decoded byte array. 464 | * 465 | * @param source the Base64 encoded data 466 | * @param off the offset of where to begin decoding 467 | * @param len the length of characters to decode 468 | * @return decoded data 469 | * @since 1.3 470 | * @throws Base64DecoderException 471 | */ 472 | public static byte[] decode(byte[] source, int off, int len) 473 | throws Base64DecoderException { 474 | return decode(source, off, len, DECODABET); 475 | } 476 | 477 | /** 478 | * Decodes web safe Base64 content in byte array format and returns 479 | * the decoded byte array. 480 | * Web safe encoding uses '-' instead of '+', '_' instead of '/' 481 | * 482 | * @param source the Base64 encoded data 483 | * @param off the offset of where to begin decoding 484 | * @param len the length of characters to decode 485 | * @return decoded data 486 | */ 487 | public static byte[] decodeWebSafe(byte[] source, int off, int len) 488 | throws Base64DecoderException { 489 | return decode(source, off, len, WEBSAFE_DECODABET); 490 | } 491 | 492 | /** 493 | * Decodes Base64 content using the supplied decodabet and returns 494 | * the decoded byte array. 495 | * 496 | * @param source the Base64 encoded data 497 | * @param off the offset of where to begin decoding 498 | * @param len the length of characters to decode 499 | * @param decodabet the decodabet for decoding Base64 content 500 | * @return decoded data 501 | */ 502 | public static byte[] decode(byte[] source, int off, int len, byte[] decodabet) 503 | throws Base64DecoderException { 504 | int len34 = len * 3 / 4; 505 | byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output 506 | int outBuffPosn = 0; 507 | 508 | byte[] b4 = new byte[4]; 509 | int b4Posn = 0; 510 | int i = 0; 511 | byte sbiCrop = 0; 512 | byte sbiDecode = 0; 513 | for (i = 0; i < len; i++) { 514 | sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits 515 | sbiDecode = decodabet[sbiCrop]; 516 | 517 | if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better 518 | if (sbiDecode >= EQUALS_SIGN_ENC) { 519 | // An equals sign (for padding) must not occur at position 0 or 1 520 | // and must be the last byte[s] in the encoded value 521 | if (sbiCrop == EQUALS_SIGN) { 522 | int bytesLeft = len - i; 523 | byte lastByte = (byte) (source[len - 1 + off] & 0x7f); 524 | if (b4Posn == 0 || b4Posn == 1) { 525 | throw new Base64DecoderException( 526 | "invalid padding byte '=' at byte offset " + i); 527 | } else if ((b4Posn == 3 && bytesLeft > 2) 528 | || (b4Posn == 4 && bytesLeft > 1)) { 529 | throw new Base64DecoderException( 530 | "padding byte '=' falsely signals end of encoded value " 531 | + "at offset " + i); 532 | } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) { 533 | throw new Base64DecoderException( 534 | "encoded value has invalid trailing byte"); 535 | } 536 | break; 537 | } 538 | 539 | b4[b4Posn++] = sbiCrop; 540 | if (b4Posn == 4) { 541 | outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); 542 | b4Posn = 0; 543 | } 544 | } 545 | } else { 546 | throw new Base64DecoderException("Bad Base64 input character at " + i 547 | + ": " + source[i + off] + "(decimal)"); 548 | } 549 | } 550 | 551 | // Because web safe encoding allows non padding base64 encodes, we 552 | // need to pad the rest of the b4 buffer with equal signs when 553 | // b4Posn != 0. There can be at most 2 equal signs at the end of 554 | // four characters, so the b4 buffer must have two or three 555 | // characters. This also catches the case where the input is 556 | // padded with EQUALS_SIGN 557 | if (b4Posn != 0) { 558 | if (b4Posn == 1) { 559 | throw new Base64DecoderException("single trailing character at offset " 560 | + (len - 1)); 561 | } 562 | b4[b4Posn++] = EQUALS_SIGN; 563 | outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet); 564 | } 565 | 566 | byte[] out = new byte[outBuffPosn]; 567 | System.arraycopy(outBuff, 0, out, 0, outBuffPosn); 568 | return out; 569 | } 570 | } 571 | -------------------------------------------------------------------------------- /android/data/Base64DecoderException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2002, Google, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package org.godotengine.godot.data; 16 | 17 | /** 18 | * Exception thrown when encountering an invalid Base64 input character. 19 | * 20 | * @author nelson 21 | */ 22 | public class Base64DecoderException extends Exception { 23 | public Base64DecoderException() { 24 | super(); 25 | } 26 | 27 | public Base64DecoderException(String s) { 28 | super(s); 29 | } 30 | 31 | private static final long serialVersionUID = 1L; 32 | } 33 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | 2 | def can_build(plat): 3 | return plat == "android" 4 | 5 | def configure(env): 6 | if env["platform"] == "android": 7 | env.android_add_java_dir("android"); 8 | env.android_add_to_manifest("android/AndroidManifestChunk.xml") 9 | -------------------------------------------------------------------------------- /config.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrogSquare/GodotSQL/5950a48d8534023b5cfab9c61eaf18394d237f30/config.pyc -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | --------------------------------------------------------------------------------