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 33 #define ENABLE_ANDROID_LOG 0 34 #define SMALL_BUFFER_SIZE 10 35 #define PHONE_NUMBER_BUFFER_SIZE 40 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 // ALOGE("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 static void phone_numbers_equal(sqlite3_context * context, int argc, sqlite3_value ** argv) 77 { 78 if (argc != 2 && argc != 3) { 79 sqlite3_result_int(context, 0); 80 return; 81 } 82 83 char const * num1 = (char const *)sqlite3_value_text(argv[0]); 84 char const * num2 = (char const *)sqlite3_value_text(argv[1]); 85 86 bool use_strict = false; 87 if (argc == 3) { 88 use_strict = (sqlite3_value_int(argv[2]) != 0); 89 } 90 91 if (num1 == NULL || num2 == NULL) { 92 sqlite3_result_null(context); 93 return; 94 } 95 96 bool equal = 97 (use_strict ? 98 android::phone_number_compare_strict(num1, num2) : 99 android::phone_number_compare_loose(num1, num2)); 100 101 if (equal) { 102 sqlite3_result_int(context, 1); 103 } else { 104 sqlite3_result_int(context, 0); 105 } 106 } 107 108 static void phone_number_stripped_reversed(sqlite3_context * context, int argc, 109 sqlite3_value ** argv) 110 { 111 if (argc != 1) { 112 sqlite3_result_int(context, 0); 113 return; 114 } 115 116 char const * number = (char const *)sqlite3_value_text(argv[0]); 117 if (number == NULL) { 118 sqlite3_result_null(context); 119 return; 120 } 121 122 char out[PHONE_NUMBER_BUFFER_SIZE]; 123 int outlen = 0; 124 android::phone_number_stripped_reversed_inter(number, out, PHONE_NUMBER_BUFFER_SIZE, &outlen); 125 sqlite3_result_text(context, (const char*)out, outlen, SQLITE_TRANSIENT); 126 } 127 128 129 #if ENABLE_ANDROID_LOG 130 static void android_log(sqlite3_context * context, int argc, sqlite3_value ** argv) 131 { 132 char const * tag = "sqlite_trigger"; 133 char const * msg = ""; 134 int msgIndex = 0; 135 136 switch (argc) { 137 case 2: 138 tag = (char const *)sqlite3_value_text(argv[0]); 139 if (tag == NULL) { 140 tag = "sqlite_trigger"; 141 } 142 msgIndex = 1; 143 case 1: 144 msg = (char const *)sqlite3_value_text(argv[msgIndex]); 145 if (msg == NULL) { 146 msg = ""; 147 } 148 ALOG(LOG_INFO, tag, "%s", msg); 149 sqlite3_result_int(context, 1); 150 return; 151 152 default: 153 sqlite3_result_int(context, 0); 154 return; 155 } 156 } 157 #endif 158 159 static void delete_file(sqlite3_context * context, int argc, sqlite3_value ** argv) 160 { 161 if (argc != 1) { 162 sqlite3_result_int(context, 0); 163 return; 164 } 165 166 char const * path = (char const *)sqlite3_value_text(argv[0]); 167 // Don't allow ".." in paths 168 if (path == NULL || strstr(path, "/../") != NULL) { 169 sqlite3_result_null(context); 170 return; 171 } 172 173 // We only allow deleting files in the EXTERNAL_STORAGE path, or one of the 174 // SECONDARY_STORAGE paths 175 bool good_path = false; 176 char const * external_storage = getenv("EXTERNAL_STORAGE"); 177 if (external_storage && strncmp(external_storage, path, strlen(external_storage)) == 0) { 178 good_path = true; 179 } else { 180 // check SECONDARY_STORAGE, which should be a colon separated list of paths 181 char const * secondary_paths = getenv("SECONDARY_STORAGE"); 182 while (secondary_paths && secondary_paths[0]) { 183 const char* colon = strchr(secondary_paths, ':'); 184 int length = (colon ? colon - secondary_paths : strlen(secondary_paths)); 185 if (strncmp(secondary_paths, path, length) == 0) { 186 good_path = true; 187 } 188 secondary_paths += length; 189 while (*secondary_paths == ':') secondary_paths++; 190 } 191 } 192 193 if (!good_path) { 194 sqlite3_result_null(context); 195 return; 196 } 197 198 int err = unlink(path); 199 if (err != -1) { 200 // No error occured, return true 201 sqlite3_result_int(context, 1); 202 } else { 203 // An error occured, return false 204 sqlite3_result_int(context, 0); 205 } 206 } 207 208 static void tokenize_auxdata_delete(void * data) 209 { 210 sqlite3_stmt * statement = (sqlite3_stmt *)data; 211 sqlite3_finalize(statement); 212 } 213 214 static void base16Encode(char* dest, const char* src, uint32_t size) 215 { 216 static const char * BASE16_TABLE = "0123456789abcdef"; 217 for (uint32_t i = 0; i < size; i++) { 218 char ch = *src++; 219 *dest++ = BASE16_TABLE[ (ch & 0xf0) >> 4 ]; 220 *dest++ = BASE16_TABLE[ (ch & 0x0f) ]; 221 } 222 } 223 224 struct SqliteUserData { 225 sqlite3 * handle; 226 UCollator* collator; 227 }; 228 229 /** 230 * This function is invoked as: 231 * 232 * _TOKENIZE('<token_table>', <data_row_id>, <data>, <delimiter>, 233 * <use_token_index>, <data_tag>) 234 * 235 * If <use_token_index> is omitted, it is treated as 0. 236 * If <data_tag> is omitted, it is treated as NULL. 237 * 238 * It will split <data> on each instance of <delimiter> and insert each token 239 * into <token_table>. The following columns in <token_table> are used: 240 * token TEXT, source INTEGER, token_index INTEGER, tag (any type) 241 * The token_index column is not required if <use_token_index> is 0. 242 * The tag column is not required if <data_tag> is NULL. 243 * 244 * One row is inserted for each token in <data>. 245 * In each inserted row, 'source' is <data_row_id>. 246 * In the first inserted row, 'token' is the hex collation key of 247 * the entire <data> string, and 'token_index' is 0. 248 * In each row I (where 1 <= I < N, and N is the number of tokens in <data>) 249 * 'token' will be set to the hex collation key of the I:th token (0-based). 250 * If <use_token_index> != 0, 'token_index' is set to I. 251 * If <data_tag> is not NULL, 'tag' is set to <data_tag>. 252 * 253 * In other words, there will be one row for the entire string, 254 * and one row for each token except the first one. 255 * 256 * The function returns the number of tokens generated. 257 */ 258 static void tokenize(sqlite3_context * context, int argc, sqlite3_value ** argv) 259 { 260 //ALOGD("enter tokenize"); 261 int err; 262 int useTokenIndex = 0; 263 int useDataTag = 0; 264 265 if (!(argc >= 4 || argc <= 6)) { 266 ALOGE("Tokenize requires 4 to 6 arguments"); 267 sqlite3_result_null(context); 268 return; 269 } 270 271 if (argc > 4) { 272 useTokenIndex = sqlite3_value_int(argv[4]); 273 } 274 275 if (argc > 5) { 276 useDataTag = (sqlite3_value_type(argv[5]) != SQLITE_NULL); 277 } 278 279 sqlite3 * handle = sqlite3_context_db_handle(context); 280 UCollator* collator = (UCollator*)sqlite3_user_data(context); 281 char const * tokenTable = (char const *)sqlite3_value_text(argv[0]); 282 if (tokenTable == NULL) { 283 ALOGE("tokenTable null"); 284 sqlite3_result_null(context); 285 return; 286 } 287 288 // Get or create the prepared statement for the insertions 289 sqlite3_stmt * statement = (sqlite3_stmt *)sqlite3_get_auxdata(context, 0); 290 if (!statement) { 291 char const * tokenIndexCol = useTokenIndex ? ", token_index" : ""; 292 char const * tokenIndexParam = useTokenIndex ? ", ?" : ""; 293 char const * dataTagCol = useDataTag ? ", tag" : ""; 294 char const * dataTagParam = useDataTag ? ", ?" : ""; 295 char * sql = sqlite3_mprintf("INSERT INTO %s (token, source%s%s) VALUES (?, ?%s%s);", 296 tokenTable, tokenIndexCol, dataTagCol, tokenIndexParam, dataTagParam); 297 err = sqlite3_prepare_v2(handle, sql, -1, &statement, NULL); 298 sqlite3_free(sql); 299 if (err) { 300 ALOGE("prepare failed"); 301 sqlite3_result_null(context); 302 return; 303 } 304 // This binds the statement to the table it was compiled against, which is argv[0]. 305 // If this function is ever called with a different table the finalizer will be called 306 // and sqlite3_get_auxdata() will return null above, forcing a recompile for the new table. 307 sqlite3_set_auxdata(context, 0, statement, tokenize_auxdata_delete); 308 } else { 309 // Reset the cached statement so that binding the row ID will work properly 310 sqlite3_reset(statement); 311 } 312 313 // Bind the row ID of the source row 314 int64_t rowID = sqlite3_value_int64(argv[1]); 315 err = sqlite3_bind_int64(statement, 2, rowID); 316 if (err != SQLITE_OK) { 317 ALOGE("bind failed"); 318 sqlite3_result_null(context); 319 return; 320 } 321 322 // Bind <data_tag> to the tag column 323 if (useDataTag) { 324 int dataTagParamIndex = useTokenIndex ? 4 : 3; 325 err = sqlite3_bind_value(statement, dataTagParamIndex, argv[5]); 326 if (err != SQLITE_OK) { 327 ALOGE("bind failed"); 328 sqlite3_result_null(context); 329 return; 330 } 331 } 332 333 // Get the raw bytes for the string to tokenize 334 // the string will be modified by following code 335 // however, sqlite did not reuse the string, so it is safe to not dup it 336 UChar * origData = (UChar *)sqlite3_value_text16(argv[2]); 337 if (origData == NULL) { 338 sqlite3_result_null(context); 339 return; 340 } 341 342 // Get the raw bytes for the delimiter 343 const UChar * delim = (const UChar *)sqlite3_value_text16(argv[3]); 344 if (delim == NULL) { 345 ALOGE("can't get delimiter"); 346 sqlite3_result_null(context); 347 return; 348 } 349 350 UChar * token = NULL; 351 UChar *state; 352 int numTokens = 0; 353 354 do { 355 if (numTokens == 0) { 356 token = origData; 357 } 358 359 // Reset the program so we can use it to perform the insert 360 sqlite3_reset(statement); 361 UErrorCode status = U_ZERO_ERROR; 362 char keybuf[1024]; 363 uint32_t result = ucol_getSortKey(collator, token, -1, (uint8_t*)keybuf, sizeof(keybuf)-1); 364 if (result > sizeof(keybuf)) { 365 // TODO allocate memory for this super big string 366 ALOGE("ucol_getSortKey needs bigger buffer %d", result); 367 break; 368 } 369 uint32_t keysize = result-1; 370 uint32_t base16Size = keysize*2; 371 char *base16buf = (char*)malloc(base16Size); 372 base16Encode(base16buf, keybuf, keysize); 373 err = sqlite3_bind_text(statement, 1, base16buf, base16Size, SQLITE_STATIC); 374 375 if (err != SQLITE_OK) { 376 ALOGE(" sqlite3_bind_text16 error %d", err); 377 free(base16buf); 378 break; 379 } 380 381 if (useTokenIndex) { 382 err = sqlite3_bind_int(statement, 3, numTokens); 383 if (err != SQLITE_OK) { 384 ALOGE(" sqlite3_bind_int error %d", err); 385 free(base16buf); 386 break; 387 } 388 } 389 390 err = sqlite3_step(statement); 391 free(base16buf); 392 393 if (err != SQLITE_DONE) { 394 ALOGE(" sqlite3_step error %d", err); 395 break; 396 } 397 numTokens++; 398 if (numTokens == 1) { 399 // first call 400 u_strtok_r(origData, delim, &state); 401 } 402 } while ((token = u_strtok_r(NULL, delim, &state)) != NULL); 403 sqlite3_result_int(context, numTokens); 404 } 405 406 static void localized_collator_dtor(UCollator* collator) 407 { 408 ucol_close(collator); 409 } 410 411 #define LOCALIZED_COLLATOR_NAME "LOCALIZED" 412 413 // This collator may be removed in the near future, so you MUST not use now. 414 #define PHONEBOOK_COLLATOR_NAME "PHONEBOOK" 415 416 extern "C" int register_localized_collators(sqlite3* handle, const char* systemLocale, int utf16Storage) 417 { 418 int err; 419 UErrorCode status = U_ZERO_ERROR; 420 void* icudata; 421 422 UCollator* collator = ucol_open(systemLocale, &status); 423 if (U_FAILURE(status)) { 424 return -1; 425 } 426 427 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); 428 if (U_FAILURE(status)) { 429 return -1; 430 } 431 432 status = U_ZERO_ERROR; 433 char buf[1024]; 434 ucol_getShortDefinitionString(collator, NULL, buf, 1024, &status); 435 436 if (utf16Storage) { 437 err = sqlite3_create_collation_v2(handle, LOCALIZED_COLLATOR_NAME, SQLITE_UTF16, collator, 438 collate16, (void(*)(void*))localized_collator_dtor); 439 } else { 440 err = sqlite3_create_collation_v2(handle, LOCALIZED_COLLATOR_NAME, SQLITE_UTF8, collator, 441 collate8, (void(*)(void*))localized_collator_dtor); 442 } 443 444 if (err != SQLITE_OK) { 445 return err; 446 } 447 448 // Register the _TOKENIZE function 449 err = sqlite3_create_function(handle, "_TOKENIZE", 4, SQLITE_UTF16, collator, tokenize, NULL, NULL); 450 if (err != SQLITE_OK) { 451 return err; 452 } 453 err = sqlite3_create_function(handle, "_TOKENIZE", 5, SQLITE_UTF16, collator, tokenize, NULL, NULL); 454 if (err != SQLITE_OK) { 455 return err; 456 } 457 err = sqlite3_create_function(handle, "_TOKENIZE", 6, SQLITE_UTF16, collator, tokenize, NULL, NULL); 458 if (err != SQLITE_OK) { 459 return err; 460 } 461 462 463 //// PHONEBOOK_COLLATOR 464 status = U_ZERO_ERROR; 465 collator = ucol_open(systemLocale, &status); 466 if (U_FAILURE(status)) { 467 return -1; 468 } 469 470 status = U_ZERO_ERROR; 471 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); 472 if (U_FAILURE(status)) { 473 return -1; 474 } 475 476 status = U_ZERO_ERROR; 477 // ucol_getShortDefinitionString(collator, NULL, buf, 1024, &status); 478 if (utf16Storage) { 479 err = sqlite3_create_collation_v2(handle, PHONEBOOK_COLLATOR_NAME, SQLITE_UTF16, collator, 480 collate16, (void(*)(void*))localized_collator_dtor); 481 } else { 482 err = sqlite3_create_collation_v2(handle, PHONEBOOK_COLLATOR_NAME, SQLITE_UTF8, collator, 483 collate8, (void(*)(void*))localized_collator_dtor); 484 } 485 486 if (err != SQLITE_OK) { 487 return err; 488 } 489 //// PHONEBOOK_COLLATOR 490 491 return SQLITE_OK; 492 } 493 494 495 extern "C" int register_android_functions(sqlite3 * handle, int utf16Storage) 496 { 497 int err; 498 UErrorCode status = U_ZERO_ERROR; 499 500 UCollator * collator = ucol_open(NULL, &status); 501 if (U_FAILURE(status)) { 502 return -1; 503 } 504 505 if (utf16Storage) { 506 // Note that text should be stored as UTF-16 507 err = sqlite3_exec(handle, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); 508 if (err != SQLITE_OK) { 509 return err; 510 } 511 512 // Register the UNICODE collation 513 err = sqlite3_create_collation_v2(handle, "UNICODE", SQLITE_UTF16, collator, collate16, 514 (void(*)(void*))localized_collator_dtor); 515 } else { 516 err = sqlite3_create_collation_v2(handle, "UNICODE", SQLITE_UTF8, collator, collate8, 517 (void(*)(void*))localized_collator_dtor); 518 } 519 520 if (err != SQLITE_OK) { 521 return err; 522 } 523 524 // Register the PHONE_NUM_EQUALS function 525 err = sqlite3_create_function( 526 handle, "PHONE_NUMBERS_EQUAL", 2, 527 SQLITE_UTF8, NULL, phone_numbers_equal, NULL, NULL); 528 if (err != SQLITE_OK) { 529 return err; 530 } 531 532 // Register the PHONE_NUM_EQUALS function with an additional argument "use_strict" 533 err = sqlite3_create_function( 534 handle, "PHONE_NUMBERS_EQUAL", 3, 535 SQLITE_UTF8, NULL, phone_numbers_equal, NULL, NULL); 536 if (err != SQLITE_OK) { 537 return err; 538 } 539 540 // Register the _DELETE_FILE function 541 err = sqlite3_create_function(handle, "_DELETE_FILE", 1, SQLITE_UTF8, NULL, delete_file, NULL, NULL); 542 if (err != SQLITE_OK) { 543 return err; 544 } 545 546 #if ENABLE_ANDROID_LOG 547 // Register the _LOG function 548 err = sqlite3_create_function(handle, "_LOG", 1, SQLITE_UTF8, NULL, android_log, NULL, NULL); 549 if (err != SQLITE_OK) { 550 return err; 551 } 552 #endif 553 554 // Register the _PHONE_NUMBER_STRIPPED_REVERSED function, which imitates 555 // PhoneNumberUtils.getStrippedReversed. This function is not public API, 556 // it is only used for compatibility with Android 1.6 and earlier. 557 err = sqlite3_create_function(handle, 558 "_PHONE_NUMBER_STRIPPED_REVERSED", 559 1, SQLITE_UTF8, NULL, 560 phone_number_stripped_reversed, 561 NULL, NULL); 562 if (err != SQLITE_OK) { 563 return err; 564 } 565 566 return SQLITE_OK; 567 } 568