1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "sqlite3_android" 18 19 #include <ctype.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <unistd.h> 23 24 #include <unicode/ucol.h> 25 #include <unicode/uiter.h> 26 #include <unicode/ustring.h> 27 #include <unicode/utypes.h> 28 #include <cutils/log.h> 29 30 #include "sqlite3_android.h" 31 #include "PhoneNumberUtils.h" 32 #include "PhonebookIndex.h" 33 34 #define ENABLE_ANDROID_LOG 0 35 #define SMALL_BUFFER_SIZE 10 36 37 static int collate16(void *p, int n1, const void *v1, int n2, const void *v2) 38 { 39 UCollator *coll = (UCollator *) p; 40 UCollationResult result = ucol_strcoll(coll, (const UChar *) v1, n1, 41 (const UChar *) v2, n2); 42 43 if (result == UCOL_LESS) { 44 return -1; 45 } else if (result == UCOL_GREATER) { 46 return 1; 47 } else { 48 return 0; 49 } 50 } 51 52 static int collate8(void *p, int n1, const void *v1, int n2, const void *v2) 53 { 54 UCollator *coll = (UCollator *) p; 55 UCharIterator i1, i2; 56 UErrorCode status = U_ZERO_ERROR; 57 58 uiter_setUTF8(&i1, (const char *) v1, n1); 59 uiter_setUTF8(&i2, (const char *) v2, n2); 60 61 UCollationResult result = ucol_strcollIter(coll, &i1, &i2, &status); 62 63 if (U_FAILURE(status)) { 64 // LOGE("Collation iterator error: %d\n", status); 65 } 66 67 if (result == UCOL_LESS) { 68 return -1; 69 } else if (result == UCOL_GREATER) { 70 return 1; 71 } else { 72 return 0; 73 } 74 } 75 76 /** 77 * Obtains the first UNICODE letter from the supplied string, normalizes and returns it. 78 */ 79 static void get_phonebook_index( 80 sqlite3_context * context, int argc, sqlite3_value ** argv) 81 { 82 if (argc != 2) { 83 sqlite3_result_null(context); 84 return; 85 } 86 87 char const * src = (char const *)sqlite3_value_text(argv[0]); 88 char const * locale = (char const *)sqlite3_value_text(argv[1]); 89 if (src == NULL || src[0] == 0 || locale == NULL) { 90 sqlite3_result_null(context); 91 return; 92 } 93 94 UCharIterator iter; 95 uiter_setUTF8(&iter, src, -1); 96 97 UBool isError = FALSE; 98 UChar index[SMALL_BUFFER_SIZE]; 99 uint32_t len = android::GetPhonebookIndex(&iter, locale, index, sizeof(index), &isError); 100 if (isError) { 101 sqlite3_result_null(context); 102 return; 103 } 104 105 uint32_t outlen = 0; 106 uint8_t out[SMALL_BUFFER_SIZE]; 107 for (uint32_t i = 0; i < len; i++) { 108 U8_APPEND(out, outlen, sizeof(out), index[i], isError); 109 if (isError) { 110 sqlite3_result_null(context); 111 return; 112 } 113 } 114 115 if (outlen == 0) { 116 sqlite3_result_null(context); 117 return; 118 } 119 120 sqlite3_result_text(context, (const char*)out, outlen, SQLITE_TRANSIENT); 121 } 122 123 static void phone_numbers_equal(sqlite3_context * context, int argc, sqlite3_value ** argv) 124 { 125 if (argc != 2 && argc != 3) { 126 sqlite3_result_int(context, 0); 127 return; 128 } 129 130 char const * num1 = (char const *)sqlite3_value_text(argv[0]); 131 char const * num2 = (char const *)sqlite3_value_text(argv[1]); 132 133 bool use_strict = false; 134 if (argc == 3) { 135 use_strict = (sqlite3_value_int(argv[2]) != 0); 136 } 137 138 if (num1 == NULL || num2 == NULL) { 139 sqlite3_result_null(context); 140 return; 141 } 142 143 bool equal = 144 (use_strict ? 145 android::phone_number_compare_strict(num1, num2) : 146 android::phone_number_compare_loose(num1, num2)); 147 148 if (equal) { 149 sqlite3_result_int(context, 1); 150 } else { 151 sqlite3_result_int(context, 0); 152 } 153 } 154 155 #if ENABLE_ANDROID_LOG 156 static void android_log(sqlite3_context * context, int argc, sqlite3_value ** argv) 157 { 158 char const * tag = "sqlite_trigger"; 159 char const * msg = ""; 160 int msgIndex = 0; 161 162 switch (argc) { 163 case 2: 164 tag = (char const *)sqlite3_value_text(argv[0]); 165 if (tag == NULL) { 166 tag = "sqlite_trigger"; 167 } 168 msgIndex = 1; 169 case 1: 170 msg = (char const *)sqlite3_value_text(argv[msgIndex]); 171 if (msg == NULL) { 172 msg = ""; 173 } 174 LOG(LOG_INFO, tag, msg); 175 sqlite3_result_int(context, 1); 176 return; 177 178 default: 179 sqlite3_result_int(context, 0); 180 return; 181 } 182 } 183 #endif 184 185 static void delete_file(sqlite3_context * context, int argc, sqlite3_value ** argv) 186 { 187 if (argc != 1) { 188 sqlite3_result_int(context, 0); 189 return; 190 } 191 192 char const * path = (char const *)sqlite3_value_text(argv[0]); 193 char const * external_storage = getenv("EXTERNAL_STORAGE"); 194 if (path == NULL || external_storage == NULL) { 195 sqlite3_result_null(context); 196 return; 197 } 198 199 if (strncmp(external_storage, path, strlen(external_storage)) != 0) { 200 sqlite3_result_null(context); 201 return; 202 } 203 if (strstr(path, "/../") != NULL) { 204 sqlite3_result_null(context); 205 return; 206 } 207 208 int err = unlink(path); 209 if (err != -1) { 210 // No error occured, return true 211 sqlite3_result_int(context, 1); 212 } else { 213 // An error occured, return false 214 sqlite3_result_int(context, 0); 215 } 216 } 217 218 static void tokenize_auxdata_delete(void * data) 219 { 220 sqlite3_stmt * statement = (sqlite3_stmt *)data; 221 sqlite3_finalize(statement); 222 } 223 224 static void base16Encode(char* dest, const char* src, uint32_t size) 225 { 226 static const char * BASE16_TABLE = "0123456789abcdef"; 227 for (uint32_t i = 0; i < size; i++) { 228 char ch = *src++; 229 *dest++ = BASE16_TABLE[ (ch & 0xf0) >> 4 ]; 230 *dest++ = BASE16_TABLE[ (ch & 0x0f) ]; 231 } 232 } 233 234 struct SqliteUserData { 235 sqlite3 * handle; 236 UCollator* collator; 237 }; 238 239 /** 240 * This function is invoked as: 241 * 242 * _TOKENIZE('<token_table>', <data_row_id>, <data>, <delimiter>, 243 * <use_token_index>, <data_tag>) 244 * 245 * If <use_token_index> is omitted, it is treated as 0. 246 * If <data_tag> is omitted, it is treated as NULL. 247 * 248 * It will split <data> on each instance of <delimiter> and insert each token 249 * into <token_table>. The following columns in <token_table> are used: 250 * token TEXT, source INTEGER, token_index INTEGER, tag (any type) 251 * The token_index column is not required if <use_token_index> is 0. 252 * The tag column is not required if <data_tag> is NULL. 253 * 254 * One row is inserted for each token in <data>. 255 * In each inserted row, 'source' is <data_row_id>. 256 * In the first inserted row, 'token' is the hex collation key of 257 * the entire <data> string, and 'token_index' is 0. 258 * In each row I (where 1 <= I < N, and N is the number of tokens in <data>) 259 * 'token' will be set to the hex collation key of the I:th token (0-based). 260 * If <use_token_index> != 0, 'token_index' is set to I. 261 * If <data_tag> is not NULL, 'tag' is set to <data_tag>. 262 * 263 * In other words, there will be one row for the entire string, 264 * and one row for each token except the first one. 265 * 266 * The function returns the number of tokens generated. 267 */ 268 static void tokenize(sqlite3_context * context, int argc, sqlite3_value ** argv) 269 { 270 //LOGD("enter tokenize"); 271 int err; 272 int useTokenIndex = 0; 273 int useDataTag = 0; 274 275 if (!(argc >= 4 || argc <= 6)) { 276 LOGE("Tokenize requires 4 to 6 arguments"); 277 sqlite3_result_null(context); 278 return; 279 } 280 281 if (argc > 4) { 282 useTokenIndex = sqlite3_value_int(argv[4]); 283 } 284 285 if (argc > 5) { 286 useDataTag = (sqlite3_value_type(argv[5]) != SQLITE_NULL); 287 } 288 289 sqlite3 * handle = sqlite3_context_db_handle(context); 290 UCollator* collator = (UCollator*)sqlite3_user_data(context); 291 char const * tokenTable = (char const *)sqlite3_value_text(argv[0]); 292 if (tokenTable == NULL) { 293 LOGE("tokenTable null"); 294 sqlite3_result_null(context); 295 return; 296 } 297 298 // Get or create the prepared statement for the insertions 299 sqlite3_stmt * statement = (sqlite3_stmt *)sqlite3_get_auxdata(context, 0); 300 if (!statement) { 301 char const * tokenIndexCol = useTokenIndex ? ", token_index" : ""; 302 char const * tokenIndexParam = useTokenIndex ? ", ?" : ""; 303 char const * dataTagCol = useDataTag ? ", tag" : ""; 304 char const * dataTagParam = useDataTag ? ", ?" : ""; 305 char * sql = sqlite3_mprintf("INSERT INTO %s (token, source%s%s) VALUES (?, ?%s%s);", 306 tokenTable, tokenIndexCol, dataTagCol, tokenIndexParam, dataTagParam); 307 err = sqlite3_prepare_v2(handle, sql, -1, &statement, NULL); 308 sqlite3_free(sql); 309 if (err) { 310 LOGE("prepare failed"); 311 sqlite3_result_null(context); 312 return; 313 } 314 // This binds the statement to the table it was compiled against, which is argv[0]. 315 // If this function is ever called with a different table the finalizer will be called 316 // and sqlite3_get_auxdata() will return null above, forcing a recompile for the new table. 317 sqlite3_set_auxdata(context, 0, statement, tokenize_auxdata_delete); 318 } else { 319 // Reset the cached statement so that binding the row ID will work properly 320 sqlite3_reset(statement); 321 } 322 323 // Bind the row ID of the source row 324 int64_t rowID = sqlite3_value_int64(argv[1]); 325 err = sqlite3_bind_int64(statement, 2, rowID); 326 if (err != SQLITE_OK) { 327 LOGE("bind failed"); 328 sqlite3_result_null(context); 329 return; 330 } 331 332 // Bind <data_tag> to the tag column 333 if (useDataTag) { 334 int dataTagParamIndex = useTokenIndex ? 4 : 3; 335 err = sqlite3_bind_value(statement, dataTagParamIndex, argv[5]); 336 if (err != SQLITE_OK) { 337 LOGE("bind failed"); 338 sqlite3_result_null(context); 339 return; 340 } 341 } 342 343 // Get the raw bytes for the string to tokenize 344 // the string will be modified by following code 345 // however, sqlite did not reuse the string, so it is safe to not dup it 346 UChar * origData = (UChar *)sqlite3_value_text16(argv[2]); 347 if (origData == NULL) { 348 sqlite3_result_null(context); 349 return; 350 } 351 352 // Get the raw bytes for the delimiter 353 const UChar * delim = (const UChar *)sqlite3_value_text16(argv[3]); 354 if (delim == NULL) { 355 LOGE("can't get delimiter"); 356 sqlite3_result_null(context); 357 return; 358 } 359 360 UChar * token = NULL; 361 UChar *state; 362 int numTokens = 0; 363 364 do { 365 if (numTokens == 0) { 366 token = origData; 367 } 368 369 // Reset the program so we can use it to perform the insert 370 sqlite3_reset(statement); 371 UErrorCode status = U_ZERO_ERROR; 372 char keybuf[1024]; 373 uint32_t result = ucol_getSortKey(collator, token, -1, (uint8_t*)keybuf, sizeof(keybuf)-1); 374 if (result > sizeof(keybuf)) { 375 // TODO allocate memory for this super big string 376 LOGE("ucol_getSortKey needs bigger buffer %d", result); 377 break; 378 } 379 uint32_t keysize = result-1; 380 uint32_t base16Size = keysize*2; 381 char *base16buf = (char*)malloc(base16Size); 382 base16Encode(base16buf, keybuf, keysize); 383 err = sqlite3_bind_text(statement, 1, base16buf, base16Size, SQLITE_STATIC); 384 385 if (err != SQLITE_OK) { 386 LOGE(" sqlite3_bind_text16 error %d", err); 387 free(base16buf); 388 break; 389 } 390 391 if (useTokenIndex) { 392 err = sqlite3_bind_int(statement, 3, numTokens); 393 if (err != SQLITE_OK) { 394 LOGE(" sqlite3_bind_int error %d", err); 395 free(base16buf); 396 break; 397 } 398 } 399 400 err = sqlite3_step(statement); 401 free(base16buf); 402 403 if (err != SQLITE_DONE) { 404 LOGE(" sqlite3_step error %d", err); 405 break; 406 } 407 numTokens++; 408 if (numTokens == 1) { 409 // first call 410 u_strtok_r(origData, delim, &state); 411 } 412 } while ((token = u_strtok_r(NULL, delim, &state)) != NULL); 413 sqlite3_result_int(context, numTokens); 414 } 415 416 static void localized_collator_dtor(UCollator* collator) 417 { 418 ucol_close(collator); 419 } 420 421 #define LOCALIZED_COLLATOR_NAME "LOCALIZED" 422 423 // This collator may be removed in the near future, so you MUST not use now. 424 #define PHONEBOOK_COLLATOR_NAME "PHONEBOOK" 425 426 extern "C" int register_localized_collators(sqlite3* handle, const char* systemLocale, int utf16Storage) 427 { 428 int err; 429 UErrorCode status = U_ZERO_ERROR; 430 void* icudata; 431 432 UCollator* collator = ucol_open(systemLocale, &status); 433 if (U_FAILURE(status)) { 434 return -1; 435 } 436 437 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); 438 if (U_FAILURE(status)) { 439 return -1; 440 } 441 442 status = U_ZERO_ERROR; 443 char buf[1024]; 444 ucol_getShortDefinitionString(collator, NULL, buf, 1024, &status); 445 446 if (utf16Storage) { 447 err = sqlite3_create_collation_v2(handle, LOCALIZED_COLLATOR_NAME, SQLITE_UTF16, collator, 448 collate16, (void(*)(void*))localized_collator_dtor); 449 } else { 450 err = sqlite3_create_collation_v2(handle, LOCALIZED_COLLATOR_NAME, SQLITE_UTF8, collator, 451 collate8, (void(*)(void*))localized_collator_dtor); 452 } 453 454 if (err != SQLITE_OK) { 455 return err; 456 } 457 458 // Register the _TOKENIZE function 459 err = sqlite3_create_function(handle, "_TOKENIZE", 4, SQLITE_UTF16, collator, tokenize, NULL, NULL); 460 if (err != SQLITE_OK) { 461 return err; 462 } 463 err = sqlite3_create_function(handle, "_TOKENIZE", 5, SQLITE_UTF16, collator, tokenize, NULL, NULL); 464 if (err != SQLITE_OK) { 465 return err; 466 } 467 err = sqlite3_create_function(handle, "_TOKENIZE", 6, SQLITE_UTF16, collator, tokenize, NULL, NULL); 468 if (err != SQLITE_OK) { 469 return err; 470 } 471 472 473 //// PHONEBOOK_COLLATOR 474 // The collator may be removed in the near future. Do not depend on it. 475 // TODO: it might be better to have another function for registering phonebook collator. 476 status = U_ZERO_ERROR; 477 if (strcmp(systemLocale, "ja") == 0 || strcmp(systemLocale, "ja_JP") == 0) { 478 collator = ucol_open("ja@collation=phonebook", &status); 479 } else { 480 collator = ucol_open(systemLocale, &status); 481 } 482 if (U_FAILURE(status)) { 483 return -1; 484 } 485 486 status = U_ZERO_ERROR; 487 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); 488 if (U_FAILURE(status)) { 489 return -1; 490 } 491 492 status = U_ZERO_ERROR; 493 // ucol_getShortDefinitionString(collator, NULL, buf, 1024, &status); 494 if (utf16Storage) { 495 err = sqlite3_create_collation_v2(handle, PHONEBOOK_COLLATOR_NAME, SQLITE_UTF16, collator, 496 collate16, (void(*)(void*))localized_collator_dtor); 497 } else { 498 err = sqlite3_create_collation_v2(handle, PHONEBOOK_COLLATOR_NAME, SQLITE_UTF8, collator, 499 collate8, (void(*)(void*))localized_collator_dtor); 500 } 501 502 if (err != SQLITE_OK) { 503 return err; 504 } 505 //// PHONEBOOK_COLLATOR 506 507 return SQLITE_OK; 508 } 509 510 511 extern "C" int register_android_functions(sqlite3 * handle, int utf16Storage) 512 { 513 int err; 514 UErrorCode status = U_ZERO_ERROR; 515 516 UCollator * collator = ucol_open(NULL, &status); 517 if (U_FAILURE(status)) { 518 return -1; 519 } 520 521 if (utf16Storage) { 522 // Note that text should be stored as UTF-16 523 err = sqlite3_exec(handle, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); 524 if (err != SQLITE_OK) { 525 return err; 526 } 527 528 // Register the UNICODE collation 529 err = sqlite3_create_collation_v2(handle, "UNICODE", SQLITE_UTF16, collator, collate16, 530 (void(*)(void*))localized_collator_dtor); 531 } else { 532 err = sqlite3_create_collation_v2(handle, "UNICODE", SQLITE_UTF8, collator, collate8, 533 (void(*)(void*))localized_collator_dtor); 534 } 535 536 if (err != SQLITE_OK) { 537 return err; 538 } 539 540 // Register the PHONE_NUM_EQUALS function 541 err = sqlite3_create_function( 542 handle, "PHONE_NUMBERS_EQUAL", 2, 543 SQLITE_UTF8, NULL, phone_numbers_equal, NULL, NULL); 544 if (err != SQLITE_OK) { 545 return err; 546 } 547 548 // Register the PHONE_NUM_EQUALS function with an additional argument "use_strict" 549 err = sqlite3_create_function( 550 handle, "PHONE_NUMBERS_EQUAL", 3, 551 SQLITE_UTF8, NULL, phone_numbers_equal, NULL, NULL); 552 if (err != SQLITE_OK) { 553 return err; 554 } 555 556 // Register the _DELETE_FILE function 557 err = sqlite3_create_function(handle, "_DELETE_FILE", 1, SQLITE_UTF8, NULL, delete_file, NULL, NULL); 558 if (err != SQLITE_OK) { 559 return err; 560 } 561 562 #if ENABLE_ANDROID_LOG 563 // Register the _LOG function 564 err = sqlite3_create_function(handle, "_LOG", 1, SQLITE_UTF8, NULL, android_log, NULL, NULL); 565 if (err != SQLITE_OK) { 566 return err; 567 } 568 #endif 569 570 // Register the GET_PHONEBOOK_INDEX function 571 err = sqlite3_create_function(handle, 572 "GET_PHONEBOOK_INDEX", 573 2, SQLITE_UTF8, NULL, 574 get_phonebook_index, 575 NULL, NULL); 576 if (err != SQLITE_OK) { 577 return err; 578 } 579 580 return SQLITE_OK; 581 } 582