2 * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser Android is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.helpers
22 import android.content.ContentValues
23 import android.content.Context
24 import android.database.Cursor
25 import android.database.DatabaseUtils
26 import android.database.sqlite.SQLiteDatabase
27 import android.database.sqlite.SQLiteOpenHelper
29 // Define the class constants.
30 private const val SCHEMA_VERSION = 1
32 class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOKMARKS_DATABASE, null, SCHEMA_VERSION) {
33 // Define the public companion object constants. These can be moved to public class constants once the entire project has migrated to Kotlin.
35 // Define the public database constants.
36 const val BOOKMARKS_DATABASE = "bookmarks.db"
37 const val BOOKMARKS_TABLE = "bookmarks"
39 // Define the public schema constants.
41 const val BOOKMARK_NAME = "bookmarkname"
42 const val BOOKMARK_URL = "bookmarkurl"
43 const val PARENT_FOLDER = "parentfolder"
44 const val DISPLAY_ORDER = "displayorder"
45 const val IS_FOLDER = "isfolder"
46 const val FAVORITE_ICON = "favoriteicon"
48 // Define the public table creation constant.
49 const val CREATE_BOOKMARKS_TABLE = "CREATE TABLE $BOOKMARKS_TABLE (" +
50 "$ID INTEGER PRIMARY KEY, " +
51 "$BOOKMARK_NAME TEXT, " +
52 "$BOOKMARK_URL TEXT, " +
53 "$PARENT_FOLDER TEXT, " +
54 "$DISPLAY_ORDER INTEGER, " +
55 "$IS_FOLDER BOOLEAN, " +
56 "$FAVORITE_ICON BLOB)"
59 override fun onCreate(bookmarksDatabase: SQLiteDatabase) {
60 // Create the bookmarks table.
61 bookmarksDatabase.execSQL(CREATE_BOOKMARKS_TABLE)
64 override fun onUpgrade(bookmarksDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
65 // Code for upgrading the database will be added here when the schema version > 1.
69 fun createBookmark(bookmarkName: String, bookmarkURL: String, parentFolder: String, displayOrder: Int, favoriteIcon: ByteArray) {
70 // Store the bookmark data in a content values.
71 val bookmarkContentValues = ContentValues()
73 // The ID is created automatically.
74 bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName)
75 bookmarkContentValues.put(BOOKMARK_URL, bookmarkURL)
76 bookmarkContentValues.put(PARENT_FOLDER, parentFolder)
77 bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
78 bookmarkContentValues.put(IS_FOLDER, false)
79 bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon)
81 // Get a writable database handle.
82 val bookmarksDatabase = this.writableDatabase
85 bookmarksDatabase.insert(BOOKMARKS_TABLE, null, bookmarkContentValues)
87 // Close the database handle.
88 bookmarksDatabase.close()
91 // Create a bookmark from content values.
92 fun createBookmark(contentValues: ContentValues) {
93 // Get a writable database.
94 val bookmarksDatabase = this.writableDatabase
97 bookmarksDatabase.insert(BOOKMARKS_TABLE, null, contentValues)
99 // Close the database handle.
100 bookmarksDatabase.close()
104 fun createFolder(folderName: String, parentFolder: String, favoriteIcon: ByteArray) {
105 // Store the bookmark folder data in a content values.
106 val bookmarkFolderContentValues = ContentValues()
108 // The ID is created automatically. Folders are always created at the top of the list.
109 bookmarkFolderContentValues.put(BOOKMARK_NAME, folderName)
110 bookmarkFolderContentValues.put(PARENT_FOLDER, parentFolder)
111 bookmarkFolderContentValues.put(DISPLAY_ORDER, 0)
112 bookmarkFolderContentValues.put(IS_FOLDER, true)
113 bookmarkFolderContentValues.put(FAVORITE_ICON, favoriteIcon)
115 // Get a writable database handle.
116 val bookmarksDatabase = this.writableDatabase
118 // Insert the new folder.
119 bookmarksDatabase.insert(BOOKMARKS_TABLE, null, bookmarkFolderContentValues)
121 // Close the database handle.
122 bookmarksDatabase.close()
125 // Get a cursor for the bookmark with the specified database ID.
126 fun getBookmark(databaseId: Int): Cursor {
127 // Get a readable database handle.
128 val bookmarksDatabase = this.readableDatabase
130 // Return the cursor for the database ID. The cursor can't be closed because it is used in the parent activity.
131 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
134 // Get the folder name for the specified database ID.
135 fun getFolderName(databaseId: Int): String {
136 // Get a readable database handle.
137 val bookmarksDatabase = this.readableDatabase
139 // Get the cursor for the folder with the specified database ID.
140 val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
142 // Move to the first record.
143 folderCursor.moveToFirst()
145 // Get the folder name.
146 val folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME))
148 // Close the cursor and the database handle.
150 bookmarksDatabase.close()
152 // Return the folder name.
156 // Get the database ID for the specified folder name.
157 fun getFolderDatabaseId(folderName: String): Int {
158 // Get a readable database handle.
159 val bookmarksDatabase = this.readableDatabase
161 // SQL escape the folder name.
162 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
164 // Get the cursor for the folder with the specified name.
165 val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
167 // Move to the first record.
168 folderCursor.moveToFirst()
170 // Get the database ID.
171 val databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID))
173 // Close the cursor and the database handle.
175 bookmarksDatabase.close()
177 // Return the database ID.
181 // Get a cursor for the specified folder name.
182 fun getFolder(folderName: String): Cursor {
183 // Get a readable database handle.
184 val bookmarksDatabase = this.readableDatabase
186 // SQL escape the folder name.
187 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
189 // Return the cursor for the specified folder. The cursor can't be closed because it is used in the parent activity.
190 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
193 // Get a cursor of all the folders except those specified.
194 fun getFoldersExcept(exceptFolders: String): Cursor {
195 // Get a readable database handle.
196 val bookmarksDatabase = this.readableDatabase
198 // Return the cursor of all folders except those specified. Each individual folder in the list has already been SQL escaped. The cursor can't be closed because it is used in the parent activity.
199 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME NOT IN ($exceptFolders) ORDER BY $BOOKMARK_NAME ASC", null)
202 // Get a cursor with all the subfolders of the specified folder.
203 fun getSubfolders(currentFolder: String): Cursor {
204 // Get a readable database handle.
205 val bookmarksDatabase = this.readableDatabase
207 // SQL escape the current folder.
208 val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
210 // Return the cursor with the subfolders. The cursor can't be closed because it is used in the parent activity.
211 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedCurrentFolder AND $IS_FOLDER = 1", null)
214 // Get the name of the parent folder.
215 fun getParentFolderName(currentFolder: String): String {
216 // Get a readable database handle.
217 val bookmarksDatabase = this.readableDatabase
219 // SQL escape the current folder.
220 val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder)
222 // Get a cursor for the current folder.
223 val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME = $sqlEscapedCurrentFolder", null)
225 // Move to the first record.
226 bookmarkCursor.moveToFirst()
228 // Store the name of the parent folder.
229 val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
231 // Close the cursor and the database.
232 bookmarkCursor.close()
233 bookmarksDatabase.close()
235 // Return the parent folder string.
239 // Get the name of the parent folder.
240 fun getParentFolderName(databaseId: Int): String {
241 // Get a readable database handle.
242 val bookmarksDatabase = this.readableDatabase
244 // Get a cursor for the specified database ID.
245 val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
247 // Move to the first record.
248 bookmarkCursor.moveToFirst()
250 // Store the name of the parent folder.
251 val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER))
253 // Close the cursor and the database.
254 bookmarkCursor.close()
255 bookmarksDatabase.close()
257 // Return the parent folder string.
261 // Get a cursor of all the folders.
262 val allFolders: Cursor
264 // Get a readable database handle.
265 val bookmarksDatabase = this.readableDatabase
267 // Return the cursor with the all the folders. The cursor cannot be closed because it is used in the parent activity.
268 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 ORDER BY $BOOKMARK_NAME ASC", null)
271 // Get a cursor for all bookmarks and folders.
272 val allBookmarks: Cursor
274 // Get a readable database handle.
275 val bookmarksDatabase = this.readableDatabase
277 // Return a cursor with the entire contents of the bookmarks table. The cursor cannot be closed because it is used in the parent activity.
278 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE", null)
281 // Get a cursor for all bookmarks and folders ordered by display order.
282 val allBookmarksByDisplayOrder: Cursor
284 // Get a readable database handle.
285 val bookmarksDatabase = this.readableDatabase
287 // Return a cursor with the entire contents of the bookmarks table ordered by the display order. The cursor cannot be closed because it is used in the parent activity.
288 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE ORDER BY $DISPLAY_ORDER ASC", null)
291 // Get a cursor for all bookmarks and folders except those with the specified IDs.
292 fun getAllBookmarksExcept(exceptIdLongArray: LongArray): Cursor {
293 // Get a readable database handle.
294 val bookmarksDatabase = this.readableDatabase
296 // Prepare a string builder to contain the comma-separated list of IDs not to get.
297 val idsNotToGetStringBuilder = StringBuilder()
299 // Extract the array of IDs not to get to the string builder.
300 for (databaseIdLong in exceptIdLongArray) {
301 // Check to see if there is already a number in the builder.
302 if (idsNotToGetStringBuilder.isNotEmpty()) {
303 // This is not the first number, so place a `,` before the new number.
304 idsNotToGetStringBuilder.append(",")
307 // Add the new number to the builder.
308 idsNotToGetStringBuilder.append(databaseIdLong)
311 // Return a cursor with all the bookmarks except those specified. The cursor cannot be closed because it is used in the parent activity.
312 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder)", null)
315 // Get a cursor for all bookmarks and folders by display order except those with the specified IDs.
316 fun getAllBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray): Cursor {
317 // Get a readable database handle.
318 val bookmarksDatabase = this.readableDatabase
320 // Prepare a string builder to contain the comma-separated list of IDs not to get.
321 val idsNotToGetStringBuilder = StringBuilder()
323 // Extract the array of IDs not to get to the string builder.
324 for (databaseIdLong in exceptIdLongArray) {
325 // Check to see if there is already a number in the builder.
326 if (idsNotToGetStringBuilder.isNotEmpty()) {
327 // This is not the first number, so place a `,` before the new number.
328 idsNotToGetStringBuilder.append(",")
331 // Add the new number to the builder.
332 idsNotToGetStringBuilder.append(databaseIdLong)
335 // Return a cursor with all the bookmarks except those specified ordered by display order. The cursor cannot be closed because it is used in the parent activity.
336 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", null)
339 // Get a cursor for bookmarks and folders in the specified folder.
340 fun getBookmarks(folderName: String): Cursor {
341 // Get a readable database handle.
342 val bookmarksDatabase = this.readableDatabase
344 // SQL escape the folder name.
345 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
347 // Return a cursor with all the bookmarks in a specified folder. The cursor cannot be closed because it is used in the parent activity.
348 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
351 // Get a cursor for bookmarks and folders in the specified folder ordered by display order.
352 fun getBookmarksByDisplayOrder(folderName: String): Cursor {
353 // Get a readable database handle.
354 val bookmarksDatabase = this.readableDatabase
356 // SQL escape the folder name.
357 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
359 // Return a cursor with all the bookmarks in the specified folder ordered by display order. The cursor cannot be closed because it is used in the parent activity.
360 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName ORDER BY $DISPLAY_ORDER ASC", null)
363 // Get a cursor with just database ID of bookmarks and folders in the specified folder. This is useful for deleting folders with bookmarks that have favorite icons too large to fit in a cursor.
364 fun getBookmarkIds(folderName: String): Cursor {
365 // Get a readable database handle.
366 val bookmarksDatabase = this.readableDatabase
368 // SQL escape the folder name.
369 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
371 // Return a cursor with all the database IDs. The cursor cannot be closed because it is used in the parent activity.
372 return bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null)
375 // Get a cursor for bookmarks and folders in the specified folder except those with the specified IDs.
376 fun getBookmarksExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
377 // Get a readable database handle.
378 val bookmarksDatabase = this.readableDatabase
380 // Prepare a string builder to contain the comma-separated list of IDs not to get.
381 val idsNotToGetStringBuilder = StringBuilder()
383 // Extract the array of IDs not to get to the string builder.
384 for (databaseIdLong in exceptIdLongArray) {
385 // Check to see if there is already a number in the builder.
386 if (idsNotToGetStringBuilder.isNotEmpty()) {
387 // This is not the first number, so place a `,` before the new number.
388 idsNotToGetStringBuilder.append(",")
391 // Add the new number to the builder.
392 idsNotToGetStringBuilder.append(databaseIdLong)
395 // SQL escape the folder name.
396 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
398 // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified. The cursor cannot be closed because it is used in the parent activity.
399 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder)", null)
402 // Get a cursor for bookmarks and folders in the specified folder by display order except those with the specified IDs.
403 fun getBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray, folderName: String): Cursor {
404 // Get a readable database handle.
405 val bookmarksDatabase = this.readableDatabase
407 // Prepare a string builder to contain the comma-separated list of IDs not to get.
408 val idsNotToGetStringBuilder = StringBuilder()
410 // Extract the array of IDs not to get to the string builder.
411 for (databaseIdLong in exceptIdLongArray) {
412 // Check to see if there is already a number in the builder.
413 if (idsNotToGetStringBuilder.isNotEmpty()) {
414 // This is not the first number, so place a `,` before the new number.
415 idsNotToGetStringBuilder.append(",")
418 // Add the new number to the builder.
419 idsNotToGetStringBuilder.append(databaseIdLong)
422 // SQL escape the folder name.
423 val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName)
425 // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified ordered by display order.
426 // The cursor cannot be closed because it will be used in the parent activity.
427 return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC",
431 // Check if a database ID is a folder.
432 fun isFolder(databaseId: Int): Boolean {
433 // Get a readable database handle.
434 val bookmarksDatabase = this.readableDatabase
436 // Get a cursor with the is folder field for the specified database ID.
437 val folderCursor = bookmarksDatabase.rawQuery("SELECT $IS_FOLDER FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null)
439 // Move to the first record.
440 folderCursor.moveToFirst()
442 // Ascertain if this database ID is a folder.
443 val isFolder = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(IS_FOLDER)) == 1
445 // Close the cursor and the database handle.
447 bookmarksDatabase.close()
449 // Return the folder status.
453 // Update the bookmark name and URL.
454 fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String) {
455 // Initialize a content values.
456 val bookmarkContentValues = ContentValues()
458 // Store the updated values.
459 bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName)
460 bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl)
462 // Get a writable database handle.
463 val bookmarksDatabase = this.writableDatabase
465 // Update the bookmark.
466 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
468 // Close the database handle.
469 bookmarksDatabase.close()
472 // Update the bookmark name, URL, parent folder, and display order.
473 fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String, parentFolder: String, displayOrder: Int) {
474 // Initialize a content values.
475 val bookmarkContentValues = ContentValues()
477 // Store the updated values.
478 bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName)
479 bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl)
480 bookmarkContentValues.put(PARENT_FOLDER, parentFolder)
481 bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
483 // Get a writable database handle.
484 val bookmarksDatabase = this.writableDatabase
486 // Update the bookmark.
487 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
489 // Close the database handle.
490 bookmarksDatabase.close()
493 // Update the bookmark name, URL, and favorite icon.
494 fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String, favoriteIcon: ByteArray) {
495 // Initialize a content values.
496 val bookmarkContentValues = ContentValues()
498 // Store the updated values.
499 bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName)
500 bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl)
501 bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon)
503 // Get a writable database handle.
504 val bookmarksDatabase = this.writableDatabase
506 // Update the bookmark.
507 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
509 // Close the database handle.
510 bookmarksDatabase.close()
513 // Update the bookmark name, URL, parent folder, display order, and favorite icon.
514 fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String, parentFolder: String, displayOrder: Int, favoriteIcon: ByteArray) {
515 // Initialize a content values.
516 val bookmarkContentValues = ContentValues()
518 // Store the updated values.
519 bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName)
520 bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl)
521 bookmarkContentValues.put(PARENT_FOLDER, parentFolder)
522 bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
523 bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon)
525 // Get a writable database handle.
526 val bookmarksDatabase = this.writableDatabase
528 // Update the bookmark.
529 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
531 // Close the database handle.
532 bookmarksDatabase.close()
535 // Update the folder name.
536 fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String) {
537 // Get a writable database handle.
538 val bookmarksDatabase = this.writableDatabase
540 // Create a folder content values.
541 val folderContentValues = ContentValues()
543 // Store the new folder name.
544 folderContentValues.put(BOOKMARK_NAME, newFolderName)
546 // Run the update on the folder.
547 bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
549 // Create a bookmark content values.
550 val bookmarkContentValues = ContentValues()
552 // Store the new parent folder name.
553 bookmarkContentValues.put(PARENT_FOLDER, newFolderName)
555 // SQL escape the old folder name.
556 val sqlEscapedOldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName)
558 // Run the update on all the bookmarks that currently list the old folder name as their parent folder.
559 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$PARENT_FOLDER = $sqlEscapedOldFolderName", null)
561 // Close the database handle.
562 bookmarksDatabase.close()
565 // Update the folder icon.
566 fun updateFolder(databaseId: Int, folderIcon: ByteArray) {
567 // Get a writable database handle.
568 val bookmarksDatabase = this.writableDatabase
570 // Create a content values.
571 val folderContentValues = ContentValues()
573 // Store the updated icon.
574 folderContentValues.put(FAVORITE_ICON, folderIcon)
576 // Run the update on the folder.
577 bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
579 // Close the database handle.
580 bookmarksDatabase.close()
583 // Update the folder name, parent folder, and display order.
584 fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String, parentFolder: String, displayOrder: Int) {
585 // Get a writable database handle.
586 val bookmarksDatabase = this.writableDatabase
588 // Create a folder content values.
589 val folderContentValues = ContentValues()
591 // Store the new folder values.
592 folderContentValues.put(BOOKMARK_NAME, newFolderName)
593 folderContentValues.put(PARENT_FOLDER, parentFolder)
594 folderContentValues.put(DISPLAY_ORDER, displayOrder)
596 // Run the update on the folder.
597 bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
599 // Create a bookmark content values.
600 val bookmarkContentValues = ContentValues()
602 // Store the new parent folder name.
603 bookmarkContentValues.put(PARENT_FOLDER, newFolderName)
605 // SQL escape the old folder name.
606 val sqlEscapedOldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName)
608 // Run the update on all the bookmarks that currently list the old folder name as their parent folder.
609 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$PARENT_FOLDER = $sqlEscapedOldFolderName", null)
611 // Close the database handle.
612 bookmarksDatabase.close()
615 // Update the folder name and icon.
616 fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String, folderIcon: ByteArray) {
617 // Get a writable database handle.
618 val bookmarksDatabase = this.writableDatabase
620 // Create a folder content values.
621 val folderContentValues = ContentValues()
623 // Store the updated values.
624 folderContentValues.put(BOOKMARK_NAME, newFolderName)
625 folderContentValues.put(FAVORITE_ICON, folderIcon)
627 // Run the update on the folder.
628 bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
630 // Create a bookmark content values.
631 val bookmarkContentValues = ContentValues()
633 // Store the new parent folder name.
634 bookmarkContentValues.put(PARENT_FOLDER, newFolderName)
636 // SQL escape the old folder name.
637 val sqlEscapedOldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName)
639 // Run the update on all the bookmarks that currently list the old folder name as their parent folder.
640 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$PARENT_FOLDER = $sqlEscapedOldFolderName", null)
642 // Close the database handle.
643 bookmarksDatabase.close()
646 // Update the folder name and icon.
647 fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String, parentFolder: String, displayOrder: Int, folderIcon: ByteArray) {
648 // Get a writable database handle.
649 val bookmarksDatabase = this.writableDatabase
651 // Create a folder content values.
652 val folderContentValues = ContentValues()
654 // Store the updated values.
655 folderContentValues.put(BOOKMARK_NAME, newFolderName)
656 folderContentValues.put(PARENT_FOLDER, parentFolder)
657 folderContentValues.put(DISPLAY_ORDER, displayOrder)
658 folderContentValues.put(FAVORITE_ICON, folderIcon)
660 // Run the update on the folder.
661 bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
663 // Create a bookmark content values.
664 val bookmarkContentValues = ContentValues()
666 // Store the new parent folder name.
667 bookmarkContentValues.put(PARENT_FOLDER, newFolderName)
669 // SQL escape the old folder name.
670 val sqlEscapedOldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName)
672 // Run the update on all the bookmarks that currently list the old folder name as their parent folder.
673 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$PARENT_FOLDER = $sqlEscapedOldFolderName", null)
675 // Close the database handle.
676 bookmarksDatabase.close()
679 // Update the display order for one bookmark or folder.
680 fun updateDisplayOrder(databaseId: Int, displayOrder: Int) {
681 // Get a writable database handle.
682 val bookmarksDatabase = this.writableDatabase
684 // Create a content values.
685 val bookmarkContentValues = ContentValues()
687 // Store the new display order.
688 bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
690 // Update the database.
691 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
693 // Close the database handle.
694 bookmarksDatabase.close()
697 // Move one bookmark or folder to a new folder.
698 fun moveToFolder(databaseId: Int, newFolder: String) {
699 // Get a writable database handle.
700 val bookmarksDatabase = this.writableDatabase
702 // SQL escape the new folder name.
703 val sqlEscapedNewFolder = DatabaseUtils.sqlEscapeString(newFolder)
705 // Get a cursor for all the bookmarks in the new folder ordered by display order.
706 val newFolderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedNewFolder ORDER BY $DISPLAY_ORDER ASC", null)
708 // Set the new display order.
709 val displayOrder: Int = if (newFolderCursor.count > 0) { // There are already bookmarks in the folder.
710 // Move to the last bookmark.
711 newFolderCursor.moveToLast()
713 // Set the display order to be one greater that the last bookmark.
714 newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1
715 } else { // There are no bookmarks in the new folder.
716 // Set the display order to be `0`.
721 newFolderCursor.close()
723 // Create a content values.
724 val bookmarkContentValues = ContentValues()
726 // Store the new values.
727 bookmarkContentValues.put(DISPLAY_ORDER, displayOrder)
728 bookmarkContentValues.put(PARENT_FOLDER, newFolder)
730 // Update the database.
731 bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
733 // Close the database handle.
734 bookmarksDatabase.close()
737 // Delete one bookmark.
738 fun deleteBookmark(databaseId: Int) {
739 // Get a writable database handle.
740 val bookmarksDatabase = this.writableDatabase
742 // Deletes the row with the given database ID.
743 bookmarksDatabase.delete(BOOKMARKS_TABLE, "$ID = $databaseId", null)
745 // Close the database handle.
746 bookmarksDatabase.close()