From 24e573e537639f6f8ff40fd774cf9ff079bbacce Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Mon, 26 Feb 2018 09:58:18 -0800 Subject: [PATCH] Support for full backup/restore to sdcard --- protobuf/Backups.proto | 43 + protobuf/Makefile | 2 +- res/drawable-hdpi/ic_restore_white_24dp.png | Bin 0 -> 509 bytes res/drawable-mdpi/ic_restore_white_24dp.png | Bin 0 -> 332 bytes res/drawable-xhdpi/ic_restore_white_24dp.png | Bin 0 -> 643 bytes res/drawable-xxhdpi/ic_restore_white_24dp.png | Bin 0 -> 945 bytes .../ic_restore_white_24dp.png | Bin 0 -> 1276 bytes res/layout/backup_enable_dialog.xml | 95 + res/layout/enter_backup_passphrase_dialog.xml | 20 + res/layout/import_export_fragment.xml | 63 - res/layout/preference_widget_progress.xml | 23 + res/layout/registration_activity.xml | 62 +- res/values/strings.xml | 36 +- res/values/styles.xml | 9 + res/xml/preferences_chats.xml | 22 +- .../securesms/ApplicationContext.java | 2 + .../securesms/ExpirationDialog.java | 27 +- .../securesms/ImportExportFragment.java | 83 +- .../securesms/RegistrationActivity.java | 213 +- .../securesms/backup/BackupDialog.java | 86 + .../securesms/backup/BackupProtos.java | 4079 +++++++++++++++++ .../securesms/backup/FullBackupBase.java | 62 + .../securesms/backup/FullBackupExporter.java | 312 ++ .../securesms/backup/FullBackupImporter.java | 240 + .../components/SwitchPreferenceCompat.java | 16 + .../securesms/crypto/IdentityKeyUtil.java | 23 +- .../database/AttachmentDatabase.java | 18 +- .../securesms/database/DatabaseFactory.java | 8 + .../database/PlaintextBackupExporter.java | 63 - .../database/PlaintextBackupImporter.java | 3 +- .../securesms/jobs/LocalBackupJob.java | 94 + .../securesms/mms/ImageSlide.java | 12 +- .../AdvancedPreferenceFragment.java | 2 +- .../preferences/ChatsPreferenceFragment.java | 95 + .../widgets/ProgressPreference.java | 61 + .../service/LocalBackupListener.java | 39 + .../securesms/util/BackupUtil.java | 160 + .../securesms/util/DateUtils.java | 10 +- .../securesms/util/StorageUtil.java | 23 +- .../securesms/util/TextSecurePreferences.java | 29 + src/org/thoughtcrime/securesms/util/Util.java | 18 +- 41 files changed, 5884 insertions(+), 269 deletions(-) create mode 100644 protobuf/Backups.proto create mode 100644 res/drawable-hdpi/ic_restore_white_24dp.png create mode 100644 res/drawable-mdpi/ic_restore_white_24dp.png create mode 100644 res/drawable-xhdpi/ic_restore_white_24dp.png create mode 100644 res/drawable-xxhdpi/ic_restore_white_24dp.png create mode 100644 res/drawable-xxxhdpi/ic_restore_white_24dp.png create mode 100644 res/layout/backup_enable_dialog.xml create mode 100644 res/layout/enter_backup_passphrase_dialog.xml create mode 100644 res/layout/preference_widget_progress.xml create mode 100644 src/org/thoughtcrime/securesms/backup/BackupDialog.java create mode 100644 src/org/thoughtcrime/securesms/backup/BackupProtos.java create mode 100644 src/org/thoughtcrime/securesms/backup/FullBackupBase.java create mode 100644 src/org/thoughtcrime/securesms/backup/FullBackupExporter.java create mode 100644 src/org/thoughtcrime/securesms/backup/FullBackupImporter.java delete mode 100644 src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java create mode 100644 src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java create mode 100644 src/org/thoughtcrime/securesms/preferences/widgets/ProgressPreference.java create mode 100644 src/org/thoughtcrime/securesms/service/LocalBackupListener.java create mode 100644 src/org/thoughtcrime/securesms/util/BackupUtil.java diff --git a/protobuf/Backups.proto b/protobuf/Backups.proto new file mode 100644 index 000000000..59efed112 --- /dev/null +++ b/protobuf/Backups.proto @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2018 Open Whisper Systems + * + * Licensed according to the LICENSE file in this repository. + */ + +package signal; + +option java_package = "org.thoughtcrime.securesms.backup"; +option java_outer_classname = "BackupProtos"; + +message SqlStatement { + optional string statement = 1; +} + +message SharedPreference { + optional string file = 1; + optional string key = 2; + optional string value = 3; +} + +message Attachment { + optional uint64 rowId = 1; + optional uint64 attachmentId = 2; + optional uint32 length = 3; +} + +message DatabaseVersion { + optional uint32 version = 1; +} + +message Header { + optional bytes iv = 1; +} + +message BackupFrame { + optional Header header = 1; + optional SqlStatement statement = 2; + optional SharedPreference preference = 3; + optional Attachment attachment = 4; + optional DatabaseVersion version = 5; + optional bool end = 6; +} \ No newline at end of file diff --git a/protobuf/Makefile b/protobuf/Makefile index 241899855..d94e3c40c 100644 --- a/protobuf/Makefile +++ b/protobuf/Makefile @@ -1,3 +1,3 @@ all: - protoc --java_out=../src/ WebRtcData.proto + protoc --java_out=../src/ WebRtcData.proto Backups.proto diff --git a/res/drawable-hdpi/ic_restore_white_24dp.png b/res/drawable-hdpi/ic_restore_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..41cf4576c7b62e248efad833c2737e5c130eeccb GIT binary patch literal 509 zcmV$F|SD#)%uzxM!u zaTnAp4q5G@dGVRkucjEZ)hhs>4JbLMWWW~yFE!;uJADK^a#*F1RH@Blz@#1Jp*kPH zPbY+EU4DUa>&roRz;}Cv%vwx=+u6`@@W(-+Y=jx1;xlu}zbklI}VFXGTXFlB84 zsMa*t6NCD}b)f(h+yH$s=pi^#5IPF($Dm2jP!MVa6ESEWR277(z?=lyWDMzft8oc* zNp%XUPC-%Xjg3Omb10AdLg4-9vE4Ct6D$6?gUyw-A$OR>K4D(z>pAwiq~oZwC6!hTFNl{O@jf+E{l0* z#z`Skg;Qq0n00y3Gr$vVR!H_%YWEZ{p;^fPMZ*BT8dP%DWw(3-Fl2MFb5!HJIq{j* zYt?cORB+Bb52yp0SZ00000NkvXXu0mjfISk#o literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_restore_white_24dp.png b/res/drawable-mdpi/ic_restore_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..72c39f5eda37e6a7b9259d4e418ee7a709ffdbc8 GIT binary patch literal 332 zcmV-S0ki&zP)UGN2b1hWCd=dd4yp1_}#p=-xr8W$(4 z@phdVq^0L1_n*S5o)beq9s6JP=Y>n0TGLS~EqLua`krT!j!X2+q`?Eb z=xgUTg#+{y8Kba^&$-PiPR(QlRYuG@!^<@3VJ$UOsdx*2YN%546h~m~d);&>bS=4oo3rm?!+ZW^Z&F3yw>^L?w eaA@0d?z>-rMJX$#4*z=q0000U8 literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_restore_white_24dp.png b/res/drawable-xhdpi/ic_restore_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..235e253e689ea2cb95179d275a11f61ca751bc83 GIT binary patch literal 643 zcmV-}0(||6P)(e?viLW>~gq8$>~c z!=>~Ukqguv066xLAl-+Z0{GG0dB8^izEBqibj+6k-p>J^ zCXT-*Wb~RySR4dYbO6WdLT1OD0`3^?54;Sx@L-R3K~Lflmw*@g1N(ptArFY%0^F7c z%m510R|aMkfcw+Hn}BbHd?0oY@Om291uT~W-T{1)1`Yx9rGUo)Kc#^#V6qg@0Q{Z? z&H>d@Kn?Kszk#N7X!Zae%?BcpGd==^4^3QcMa``7!L!Z)f4KFZo8?VFI|9-K&BPkk z{0aEg6M|T)fSm|P6HOu6dwmXIONea&UWQwKxbeFwn4T0Za=fJ<9ug&v)=tpITB9w8r?(gr|b&)aU8Qc=@z)2bE#_#uwZ zUeR@%a`UcQxu5S(IWZ_l7L@-3V$@5%*E@xl=ZpxYf!GHu+4YOA3xD}d+m2V`nNt?X d=nxnJ{{V^+m^H9+BfK?Ip&)ctTpFJ*$0GNjTm20E-bgt#9Vt;`>r&TWCgWJ0fp z+uUT{2;S@u7^w}2%4|Co9Hm<#a|)#fW@~K{#J5*+&O;uObDndeUOcbQKkz0wc?i#u zL?V$$ctyYkYj+I9A|<$QBD*1 z2ukw_t*(-1H4;76@G{@f>SNNbK|w^$6hnx?b}$o>6u1SA6Sho&6k@m@##kZjv`f$^ zVb|G&SZ)imggqNKXah^=zMv0@v9)}O?l;!Q3n~-Nxf_YOd-w|7M4X_#=&sX;IBYGm z=tgaWviyRw%qGNfkFbLB6B)apgXjuKoBgBMA?bB=`)q;&DkxK=yae@d4dn)bdC+!r zLx`6k;c0YFmCGDlz@B)rd?i02(bmq%=Z0`ED4)KPBHYZK&u{mh};gSZFX zN}OPXhgn0KEd6X` z7e&f6iE_&4)xz^E;o=UveP6yj#3XTDVO=+_rvhH&HnwiDr<)get9XT*n3^L`@4s=y zIn?orbDnc-^Kr##z7&t~D(5LvWsyH=ut0?pXDF~4v7hi?F9}M5lAt8$f408?-&vy2 Tb}$0%00000NkvXXu0mjf%&4wN literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/ic_restore_white_24dp.png b/res/drawable-xxxhdpi/ic_restore_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..baccc4fc92c3dbc6498b39c53d9ab7209b9921f5 GIT binary patch literal 1276 zcmVy^=!2m(PD zhLu}_@=lCz!6=Yu0)jRL5)uuR0xbbLZKv&>#}$d^o|)2f=bSs3+|Tz9=y^!z(wUqQ z+hVa;EEbE!VwCYD%lVu`{7E+h`1tg5k&_%?8?7`^g4mc~dyTB&2L`#7e!gWDwYO71 zImt8Fn$BDun#2 z;uXFoLq5Z_xC~fHK9^ZXwZX%;jVt7qrPWnHlHB@OOF3e=J6K0LPeO}}fS2*fWfzl? zkgH`kxePPccED8n&<&783f!9vqPxZ;HUlc?ME4KV5DS~md2}b4XfI#~x(;d)ORJ|7 z-F906^U!s04`Olm=1iDvBOt*!{g;PY#PaI7Ku{;8g$JxBXn<*mgH30Upw)#2RCA4> zB;shx3F@J$uz(anyO1&MKMWG~67+r{0p;|dy1`_p0rjL&b(07mu!Nwsh|>U}ji8qB z0Y^|>qTG2v1wE(^hYgrQ(0asqfY6RA%j9qY@1n|39Z5h9L#S4U3;0fd{zMWW>_&Ak zOh73EsOCo&umDw>3FZMaQ4LcWS-@TRsG7_J-avH}i7Y_)4OP-SU^}Xfkp^r=wbeY} zAgU#i1|(7KGY>e0syWhtS*T8!2Xv#Vi!`7C)dll_0aVqI2GpQRn+N!)N+S&@Lp72= zz@rde@dE_U^6~Y6eKZ#ME7Ye4=m|EDFQ^9jh;o-NV$bsN1>N5)aQPVZtR7!@k+bN& z=dm#bw4&Op2NaUvjq!!pMw*~uHc@5#r^FULAbf&n^!f8nbX_cFoY5b1%k+S-2_9m& z=lKiWFFcOq*(7{aGxUIP2_GUMR>Eqo6Xf$np8ww$qUtkyL*v;vzP9`M3f-@WKK7tG zVEUHQvvYiH%^XMd!kFIFuP_Y|JUhqNHlF45a?>|s`q^0?%oAXcumQ2Q8otB_2B=50 zRnm*f;uR17f^**+?fBY<{)kYQs~ln zR3e6}q@8|p@mYkp33vjZ+%D5@aQ&kOk6v=~S?2Q6-y(*{C&Nw_+~V;%iG}QCn0$s< zb6jOKLmXifuk#eOR4|@0YG_~aVoL{47vuVU39IR$P*+$*N%6h_QAHcwgw@4+R2Kg$C<$6POcoP9Kk_PN zx6_w^9^!2dk>*xzu%EYh04Z#On@ymJBwN|XA6y{K2*dPop5yG{GnO))@raEH#a + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/enter_backup_passphrase_dialog.xml b/res/layout/enter_backup_passphrase_dialog.xml new file mode 100644 index 000000000..656ffd174 --- /dev/null +++ b/res/layout/enter_backup_passphrase_dialog.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/layout/import_export_fragment.xml b/res/layout/import_export_fragment.xml index 2dc20ece9..c1dca0477 100644 --- a/res/layout/import_export_fragment.xml +++ b/res/layout/import_export_fragment.xml @@ -109,68 +109,5 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/preference_widget_progress.xml b/res/layout/preference_widget_progress.xml new file mode 100644 index 000000000..3cce4b948 --- /dev/null +++ b/res/layout/preference_widget_progress.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/registration_activity.xml b/res/layout/registration_activity.xml index e34b96093..dfdac7b62 100644 --- a/res/layout/registration_activity.xml +++ b/res/layout/registration_activity.xml @@ -55,6 +55,64 @@ android:layout_centerHorizontal="true" android:layout_marginBottom="-32dp"/> + + + + + + + + + + + + + + + tools:visibility="invisible"> Remove photo - Import / export + Import Use default Use custom @@ -1326,6 +1326,40 @@ Unlock to view pending messages Unlock to complete update Please unlock Signal to complete update + Backup passphrase + Backups will be saved to external storage and encrypted with the passphrase below. You must have this passphrase in order to restore a backup. + I have written down this passphrase. Without it, I will be unable to restore a backup. + Restore backup + Skip + Register + Chat backups + Backup chats to external storage + Create backup + Enter backup passphrase + Restore + Incorrect backup password + Checking... + %d messages so far... + Restore from backup? + Restore your messages and media from a local backup. If you don\'t restore now, you won\'t be able to restore later. + Backup size: %s + Backup timestamp: %s + Enable local backups? + Enable backups + Please acknowledge your understanding by marking the confirmation check box. + Delete backups? + Disable and delete all local backups? + Delete backups + Copied to clipboard + Signal requires external storage permission in order to create backups, but it has been permanently denied. Please continue to app settings, select \"Permissions\" and enable \"External Storage\". + Last backup: %s + In progress + %d messages so far + Verify %s + Please enter the verification code sent to %s. + Wrong number? + Never + Unknown diff --git a/res/values/styles.xml b/res/values/styles.xml index c95670009..0557b0280 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -207,6 +207,15 @@ false + + + diff --git a/res/xml/preferences_chats.xml b/res/xml/preferences_chats.xml index 7ac151150..0f614a8fe 100644 --- a/res/xml/preferences_chats.xml +++ b/res/xml/preferences_chats.xml @@ -1,6 +1,7 @@ - + + + + + + + + + + + diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 3071f56e2..8c756ca04 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequiremen import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.service.ExpiringMessageManager; +import org.thoughtcrime.securesms.service.LocalBackupListener; import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener; import org.thoughtcrime.securesms.service.UpdateApkRefreshListener; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -156,6 +157,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc private void initializePeriodicTasks() { RotateSignedPreKeyListener.schedule(this); DirectoryRefreshListener.schedule(this); + LocalBackupListener.schedule(this); if (BuildConfig.PLAY_STORE_DISABLED) { UpdateApkRefreshListener.schedule(this); diff --git a/src/org/thoughtcrime/securesms/ExpirationDialog.java b/src/org/thoughtcrime/securesms/ExpirationDialog.java index 7a8a74df4..64ac9eb2b 100644 --- a/src/org/thoughtcrime/securesms/ExpirationDialog.java +++ b/src/org/thoughtcrime/securesms/ExpirationDialog.java @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms; import android.content.Context; -import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; @@ -35,12 +34,9 @@ public class ExpirationDialog extends AlertDialog { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(context.getString(R.string.ExpirationDialog_disappearing_messages)); builder.setView(view); - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - int selected = ((NumberPickerView)view.findViewById(R.id.expiration_number_picker)).getValue(); - listener.onClick(context.getResources().getIntArray(R.array.expiration_times)[selected]); - } + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { + int selected = ((NumberPickerView)view.findViewById(R.id.expiration_number_picker)).getValue(); + listener.onClick(context.getResources().getIntArray(R.array.expiration_times)[selected]); }); builder.setNegativeButton(android.R.string.cancel, null); builder.show(); @@ -49,8 +45,8 @@ public class ExpirationDialog extends AlertDialog { private static View createNumberPickerView(final Context context, final int currentExpiration) { final LayoutInflater inflater = LayoutInflater.from(context); final View view = inflater.inflate(R.layout.expiration_dialog, null); - final NumberPickerView numberPickerView = (NumberPickerView)view.findViewById(R.id.expiration_number_picker); - final TextView textView = (TextView)view.findViewById(R.id.expiration_details); + final NumberPickerView numberPickerView = view.findViewById(R.id.expiration_number_picker); + final TextView textView = view.findViewById(R.id.expiration_details); final int[] expirationTimes = context.getResources().getIntArray(R.array.expiration_times); final String[] expirationDisplayValues = new String[expirationTimes.length]; @@ -69,14 +65,11 @@ public class ExpirationDialog extends AlertDialog { numberPickerView.setMinValue(0); numberPickerView.setMaxValue(expirationTimes.length-1); - NumberPickerView.OnValueChangeListener listener = new NumberPickerView.OnValueChangeListener() { - @Override - public void onValueChange(NumberPickerView picker, int oldVal, int newVal) { - if (newVal == 0) { - textView.setText(R.string.ExpirationDialog_your_messages_will_not_expire); - } else { - textView.setText(context.getString(R.string.ExpirationDialog_your_messages_will_disappear_s_after_they_have_been_seen, picker.getDisplayedValues()[newVal])); - } + NumberPickerView.OnValueChangeListener listener = (picker, oldVal, newVal) -> { + if (newVal == 0) { + textView.setText(R.string.ExpirationDialog_your_messages_will_not_expire); + } else { + textView.setText(context.getString(R.string.ExpirationDialog_your_messages_will_disappear_s_after_they_have_been_seen, picker.getDisplayedValues()[newVal])); } }; diff --git a/src/org/thoughtcrime/securesms/ImportExportFragment.java b/src/org/thoughtcrime/securesms/ImportExportFragment.java index 2f0fa0519..ae787a707 100644 --- a/src/org/thoughtcrime/securesms/ImportExportFragment.java +++ b/src/org/thoughtcrime/securesms/ImportExportFragment.java @@ -17,7 +17,6 @@ import android.view.ViewGroup; import android.widget.Toast; import org.thoughtcrime.securesms.database.NoExternalStorageException; -import org.thoughtcrime.securesms.database.PlaintextBackupExporter; import org.thoughtcrime.securesms.database.PlaintextBackupImporter; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.service.ApplicationMigrationService; @@ -42,15 +41,13 @@ public class ImportExportFragment extends Fragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) { View layout = inflater.inflate(R.layout.import_export_fragment, container, false); View importSmsView = layout.findViewById(R.id.import_sms ); View importPlaintextView = layout.findViewById(R.id.import_plaintext_backup); - View exportPlaintextView = layout.findViewById(R.id.export_plaintext_backup); importSmsView.setOnClickListener(v -> handleImportSms()); importPlaintextView.setOnClickListener(v -> handleImportPlaintextBackup()); - exportPlaintextView.setOnClickListener(v -> handleExportPlaintextBackup()); return layout; } @@ -119,26 +116,6 @@ public class ImportExportFragment extends Fragment { builder.show(); } - @SuppressWarnings("CodeBlock2Expr") - @SuppressLint("InlinedApi") - private void handleExportPlaintextBackup() { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setIconAttribute(R.attr.dialog_alert_icon); - builder.setTitle(getActivity().getString(R.string.ExportFragment_export_plaintext_to_storage)); - builder.setMessage(getActivity().getString(R.string.ExportFragment_warning_this_will_export_the_plaintext_contents)); - builder.setPositiveButton(getActivity().getString(R.string.ExportFragment_export), (dialog, which) -> { - Permissions.with(ImportExportFragment.this) - .request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) - .ifNecessary() - .withPermanentDenialDialog(getString(R.string.ImportExportFragment_signal_needs_the_storage_permission_in_order_to_write_to_external_storage_but_it_has_been_permanently_denied)) - .onAllGranted(() -> new ExportPlaintextTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)) - .onAnyDenied(() -> Toast.makeText(getContext(), R.string.ImportExportFragment_signal_needs_the_storage_permission_in_order_to_write_to_external_storage, Toast.LENGTH_LONG).show()) - .execute(); - }); - builder.setNegativeButton(getActivity().getString(R.string.ExportFragment_cancel), null); - builder.show(); - } - @SuppressLint("StaticFieldLeak") private class ImportPlaintextBackupTask extends AsyncTask { @@ -192,62 +169,4 @@ public class ImportExportFragment extends Fragment { } } } - - @SuppressLint("StaticFieldLeak") - private class ExportPlaintextTask extends AsyncTask { - private ProgressDialog dialog; - - @Override - protected void onPreExecute() { - dialog = ProgressDialog.show(getActivity(), - getActivity().getString(R.string.ExportFragment_exporting), - getActivity().getString(R.string.ExportFragment_exporting_plaintext_to_storage), - true, false); - } - - @Override - protected Integer doInBackground(Void... params) { - try { - PlaintextBackupExporter.exportPlaintextToSd(getActivity()); - return SUCCESS; - } catch (NoExternalStorageException e) { - Log.w("ExportFragment", e); - return NO_SD_CARD; - } catch (IOException e) { - Log.w("ExportFragment", e); - return ERROR_IO; - } - } - - @Override - protected void onPostExecute(Integer result) { - Context context = getActivity(); - - if (dialog != null) - dialog.dismiss(); - - if (context == null) - return; - - switch (result) { - case NO_SD_CARD: - Toast.makeText(context, - context.getString(R.string.ExportFragment_error_unable_to_write_to_storage), - Toast.LENGTH_LONG).show(); - break; - case ERROR_IO: - Toast.makeText(context, - context.getString(R.string.ExportFragment_error_while_writing_to_storage), - Toast.LENGTH_LONG).show(); - break; - case SUCCESS: - Toast.makeText(context, - context.getString(R.string.ExportFragment_export_successful), - Toast.LENGTH_LONG).show(); - break; - } - } - } - - } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index 282714f13..287d1323d 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -26,10 +26,12 @@ import android.text.style.ClickableSpan; import android.util.Log; import android.util.Pair; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.animation.OvershootInterpolator; import android.widget.ArrayAdapter; +import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; @@ -42,22 +44,33 @@ import com.google.i18n.phonenumbers.AsYouTypeFormatter; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; +import net.sqlcipher.database.SQLiteDatabase; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; import org.thoughtcrime.securesms.animation.AnimationCompleteListener; +import org.thoughtcrime.securesms.backup.FullBackupBase; +import org.thoughtcrime.securesms.backup.FullBackupImporter; import org.thoughtcrime.securesms.components.registration.CallMeCountDownView; import org.thoughtcrime.securesms.components.registration.VerificationCodeView; import org.thoughtcrime.securesms.components.registration.VerificationPinKeyboard; +import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.IdentityDatabase; +import org.thoughtcrime.securesms.database.NoExternalStorageException; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.GcmRefreshJob; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener; +import org.thoughtcrime.securesms.util.BackupUtil; +import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.PlayServicesUtil; import org.thoughtcrime.securesms.util.PlayServicesUtil.PlayServicesStatus; @@ -75,6 +88,7 @@ import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.IOException; import java.util.List; +import java.util.Locale; /** * The register account activity. Prompts ths user for their registration information @@ -89,6 +103,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif private static final int SCENE_TRANSITION_DURATION = 250; public static final String CHALLENGE_EVENT = "org.thoughtcrime.securesms.CHALLENGE_EVENT"; public static final String CHALLENGE_EXTRA = "CAAChallenge"; + public static final String RE_REGISTRATION_EXTRA = "re_registration"; private static final String TAG = RegistrationActivity.class.getSimpleName(); @@ -106,6 +121,12 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif private View verificationContainer; private FloatingActionButton fab; + private View restoreContainer; + private TextView restoreBackupTime; + private TextView restoreBackupSize; + private TextView restoreBackupProgress; + private CircularProgressButton restoreButton; + private CallMeCountDownView callMeCountDownView; private VerificationPinKeyboard keyboard; private VerificationCodeView verificationCodeView; @@ -113,6 +134,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif private ChallengeReceiver challengeReceiver; private SignalServiceAccountManager accountManager; + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -130,6 +152,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif super.onDestroy(); shutdownChallengeListener(); markAsVerifying(false); + EventBus.getDefault().unregister(this); } @Override @@ -147,8 +170,9 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } private void initializeResources() { - TextView skipButton = findViewById(R.id.skip_button); - View informationToggle = findViewById(R.id.information_link_container); + TextView skipButton = findViewById(R.id.skip_button); + TextView restoreSkipButton = findViewById(R.id.skip_restore_button); + View informationToggle = findViewById(R.id.information_link_container); this.countrySpinner = findViewById(R.id.country_spinner); this.countryCode = findViewById(R.id.country_code); @@ -165,6 +189,13 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif this.verificationCodeView = findViewById(R.id.code); this.keyboard = findViewById(R.id.keyboard); this.callMeCountDownView = findViewById(R.id.call_me_count_down); + + this.restoreContainer = findViewById(R.id.restore_container); + this.restoreBackupSize = findViewById(R.id.backup_size_text); + this.restoreBackupTime = findViewById(R.id.backup_created_text); + this.restoreBackupProgress = findViewById(R.id.backup_progress_text); + this.restoreButton = findViewById(R.id.restore_button); + this.registrationState = new RegistrationState(RegistrationState.State.INITIAL, null, null, null); this.countryCode.addTextChangedListener(new CountryCodeChangedListener()); @@ -174,7 +205,9 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif skipButton.setOnClickListener(v -> handleCancel()); informationToggle.setOnClickListener(new InformationToggleListener()); - if (getIntent().getBooleanExtra("cancel_button", false)) { + restoreSkipButton.setOnClickListener(v -> displayInitialView(true)); + + if (getIntent().getBooleanExtra(RE_REGISTRATION_EXTRA, false)) { skipButton.setVisibility(View.VISIBLE); } else { skipButton.setVisibility(View.INVISIBLE); @@ -186,6 +219,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif }); this.verificationCodeView.setOnCompleteListener(this); + EventBus.getDefault().register(this); } @SuppressLint("ClickableViewAccessibility") @@ -247,10 +281,36 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif if (permissions.contains(Manifest.permission.READ_PHONE_STATE)) { initializeNumber(); } + + if (permissions.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + initializeBackupDetection(); + } }) .execute(); } + @SuppressLint("StaticFieldLeak") + private void initializeBackupDetection() { + if (getIntent().getBooleanExtra(RE_REGISTRATION_EXTRA, false)) return; + + new AsyncTask() { + @Override + protected @Nullable BackupUtil.BackupInfo doInBackground(Void... voids) { + try { + return BackupUtil.getLatestBackup(); + } catch (NoExternalStorageException e) { + Log.w(TAG, e); + return null; + } + } + + @Override + protected void onPostExecute(@Nullable BackupUtil.BackupInfo backup) { + if (backup != null) displayRestoreView(backup); + } + }.execute(); + } + private void setCountryDisplay(String value) { this.countrySpinnerAdapter.clear(); this.countrySpinnerAdapter.add(value); @@ -269,6 +329,60 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif number.getText().toString()); } + @SuppressLint("StaticFieldLeak") + private void handleRestore(BackupUtil.BackupInfo backup) { + View view = LayoutInflater.from(this).inflate(R.layout.enter_backup_passphrase_dialog, null); + EditText prompt = view.findViewById(R.id.restore_passphrase_input); + + new AlertDialog.Builder(this) + .setTitle(R.string.RegistrationActivity_enter_backup_passphrase) + .setView(view) + .setPositiveButton(getString(R.string.RegistrationActivity_restore), (dialog, which) -> { + restoreButton.setIndeterminateProgressMode(true); + restoreButton.setProgress(50); + + new AsyncTask() { + @Override + protected Boolean doInBackground(Void... voids) { + try { + Context context = RegistrationActivity.this; + String passphrase = prompt.getText().toString(); + SQLiteDatabase database = DatabaseFactory.getBackupDatabase(context); + + FullBackupImporter.importFile(context, + AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret(), + database, backup.getFile(), passphrase); + + DatabaseFactory.upgradeRestored(context, database); + + TextSecurePreferences.setBackupEnabled(context, true); + TextSecurePreferences.setBackupPassphrase(context, passphrase); + return true; + } catch (IOException e) { + Log.w(TAG, e); + return false; + } + } + + @Override + protected void onPostExecute(@NonNull Boolean result) { + restoreButton.setIndeterminateProgressMode(false); + restoreButton.setProgress(0); + restoreBackupProgress.setText(""); + + if (result) { + displayInitialView(true); + } else { + Toast.makeText(RegistrationActivity.this, R.string.RegistrationActivity_incorrect_backup_passphrase, Toast.LENGTH_LONG).show(); + } + } + }.execute(); + + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } + private void handleRegister() { if (TextUtils.isEmpty(countryCode.getText())) { Toast.makeText(this, getString(R.string.RegistrationActivity_you_must_specify_your_country_code), Toast.LENGTH_LONG).show(); @@ -491,11 +605,11 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } } - private void displayInitialView(@NonNull String e164number) { + private void displayRestoreView(@NonNull BackupUtil.BackupInfo backup) { title.animate().translationX(title.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { - title.setText(R.string.registration_activity__verify_your_number); + title.setText(R.string.RegistrationActivity_restore_from_backup); title.clearAnimation(); title.setTranslationX(-1 * title.getWidth()); title.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start(); @@ -505,21 +619,80 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif subtitle.animate().translationX(subtitle.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { - subtitle.setText(R.string.registration_activity__please_enter_your_mobile_number_to_receive_a_verification_code_carrier_rates_may_apply); + subtitle.setText(R.string.RegistrationActivity_restore_your_messages_and_media_from_a_local_backup); subtitle.clearAnimation(); subtitle.setTranslationX(-1 * subtitle.getWidth()); subtitle.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start(); } }).start(); - verificationContainer.animate().translationX(verificationContainer.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + registrationContainer.animate().translationX(registrationContainer.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { - verificationContainer.clearAnimation(); - verificationContainer.setVisibility(View.INVISIBLE); - verificationContainer.setTranslationX(0); + registrationContainer.clearAnimation(); + registrationContainer.setVisibility(View.INVISIBLE); + registrationContainer.setTranslationX(0); - registrationContainer.setTranslationX(-1 * registrationContainer.getWidth()); + restoreContainer.setTranslationX(-1 * registrationContainer.getWidth()); + restoreContainer.setVisibility(View.VISIBLE); + restoreButton.setProgress(0); + restoreButton.setIndeterminateProgressMode(false); + restoreButton.setOnClickListener(v -> handleRestore(backup)); + restoreBackupSize.setText(getString(R.string.RegistrationActivity_backup_size_s, Util.getPrettyFileSize(backup.getSize()))); + restoreBackupTime.setText(getString(R.string.RegistrationActivity_backup_timestamp_s, DateUtils.getExtendedRelativeTimeSpanString(RegistrationActivity.this, Locale.US, backup.getTimestamp()))); + restoreBackupProgress.setText(""); + restoreContainer.animate().translationX(0).setDuration(SCENE_TRANSITION_DURATION).setListener(null).setInterpolator(new OvershootInterpolator()).start(); + } + }).start(); + + fab.animate().rotationBy(375f).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + @Override + public void onAnimationEnd(Animator animation) { + fab.clearAnimation(); + fab.setImageResource(R.drawable.ic_restore_white_24dp); + fab.animate().rotationBy(360f).setDuration(SCENE_TRANSITION_DURATION).setListener(null).start(); + } + }).start(); + + } + + private void displayInitialView(boolean forwards) { + int startDirectionMultiplier = forwards ? -1 : 1; + int endDirectionMultiplier = forwards ? 1 : -1; + + title.animate().translationX(startDirectionMultiplier * title.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + @Override + public void onAnimationEnd(Animator animation) { + title.setText(R.string.registration_activity__verify_your_number); + title.clearAnimation(); + title.setTranslationX(endDirectionMultiplier * title.getWidth()); + title.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start(); + } + }).start(); + + subtitle.animate().translationX(startDirectionMultiplier * subtitle.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + @Override + public void onAnimationEnd(Animator animation) { + subtitle.setText(R.string.registration_activity__please_enter_your_mobile_number_to_receive_a_verification_code_carrier_rates_may_apply); + subtitle.clearAnimation(); + subtitle.setTranslationX(endDirectionMultiplier * subtitle.getWidth()); + subtitle.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start(); + } + }).start(); + + View container; + + if (verificationContainer.getVisibility() == View.VISIBLE) container = verificationContainer; + else container = restoreContainer; + + container.animate().translationX(startDirectionMultiplier * container.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + @Override + public void onAnimationEnd(Animator animation) { + container.clearAnimation(); + container.setVisibility(View.INVISIBLE); + container.setTranslationX(0); + + registrationContainer.setTranslationX(endDirectionMultiplier * registrationContainer.getWidth()); registrationContainer.setVisibility(View.VISIBLE); createButton.setProgress(0); createButton.setIndeterminateProgressMode(false); @@ -527,12 +700,12 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } }).start(); - fab.animate().rotationBy(360f).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { + fab.animate().rotationBy(startDirectionMultiplier * 360f).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { fab.clearAnimation(); fab.setImageResource(R.drawable.ic_action_name); - fab.animate().rotationBy(375f).setDuration(SCENE_TRANSITION_DURATION).setListener(null).start(); + fab.animate().rotationBy(startDirectionMultiplier * 375f).setDuration(SCENE_TRANSITION_DURATION).setListener(null).start(); } }).start(); } @@ -547,7 +720,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif title.animate().translationX(-1 * title.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { - title.setText(String.format("Verify %s", e164number)); + title.setText(getString(R.string.RegistrationActivity_verify_s, e164number)); title.clearAnimation(); title.setTranslationX(title.getWidth()); title.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start(); @@ -557,13 +730,13 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif subtitle.animate().translationX(-1 * subtitle.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { - SpannableString subtitleDescription = new SpannableString(String.format("Please enter the verification code sent to %s.", e164number)); - SpannableString wrongNumber = new SpannableString("Wrong number?"); + SpannableString subtitleDescription = new SpannableString(getString(R.string.RegistrationActivity_please_enter_the_verification_code_sent_to_s, e164number)); + SpannableString wrongNumber = new SpannableString(getString(R.string.RegistrationActivity_wrong_number)); ClickableSpan clickableSpan = new ClickableSpan() { @Override public void onClick(View widget) { - displayInitialView(e164number); + displayInitialView(false); registrationState = new RegistrationState(RegistrationState.State.INITIAL, null, null, null); } @@ -651,6 +824,12 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(FullBackupBase.BackupEvent event) { + if (event.getCount() == 0) restoreBackupProgress.setText(R.string.RegistrationActivity_checking); + else restoreBackupProgress.setText(getString(R.string.RegistrationActivity_d_messages_so_far, event.getCount())); + } + private class ChallengeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { diff --git a/src/org/thoughtcrime/securesms/backup/BackupDialog.java b/src/org/thoughtcrime/securesms/backup/BackupDialog.java new file mode 100644 index 000000000..364329049 --- /dev/null +++ b/src/org/thoughtcrime/securesms/backup/BackupDialog.java @@ -0,0 +1,86 @@ +package org.thoughtcrime.securesms.backup; + + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.TextView; +import android.widget.Toast; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.components.SwitchPreferenceCompat; +import org.thoughtcrime.securesms.service.LocalBackupListener; +import org.thoughtcrime.securesms.util.BackupUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.thoughtcrime.securesms.util.Util; + +public class BackupDialog { + + public static void showEnableBackupDialog(@NonNull Context context, @NonNull SwitchPreferenceCompat preference) { + String[] password = BackupUtil.generateBackupPassphrase(); + AlertDialog dialog = new AlertDialog.Builder(context) + .setTitle(R.string.BackupDialog_enable_local_backups) + .setView(R.layout.backup_enable_dialog) + .setPositiveButton(R.string.BackupDialog_enable_backups, null) + .setNegativeButton(android.R.string.cancel, null) + .create(); + + dialog.setOnShowListener(created -> { + Button button = ((AlertDialog) created).getButton(AlertDialog.BUTTON_POSITIVE); + button.setOnClickListener(v -> { + CheckBox confirmationCheckBox = dialog.findViewById(R.id.confirmation_check); + if (confirmationCheckBox.isChecked()) { + TextSecurePreferences.setBackupPassphrase(context, Util.join(password, " ")); + TextSecurePreferences.setBackupEnabled(context, true); + LocalBackupListener.schedule(context); + + preference.setChecked(true); + created.dismiss(); + } else { + Toast.makeText(context, R.string.BackupDialog_please_acknowledge_your_understanding_by_marking_the_confirmation_check_box, Toast.LENGTH_LONG).show(); + } + }); + }); + + dialog.show(); + + CheckBox checkBox = dialog.findViewById(R.id.confirmation_check); + TextView textView = dialog.findViewById(R.id.confirmation_text); + + ((TextView)dialog.findViewById(R.id.code_first)).setText(password[0]); + ((TextView)dialog.findViewById(R.id.code_second)).setText(password[1]); + ((TextView)dialog.findViewById(R.id.code_third)).setText(password[2]); + + ((TextView)dialog.findViewById(R.id.code_fourth)).setText(password[3]); + ((TextView)dialog.findViewById(R.id.code_fifth)).setText(password[4]); + ((TextView)dialog.findViewById(R.id.code_sixth)).setText(password[5]); + + textView.setOnClickListener(v -> checkBox.toggle()); + + dialog.findViewById(R.id.number_table).setOnClickListener(v -> { + ((ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("text", Util.join(password, " "))); + Toast.makeText(context, R.string.BackupDialog_copied_to_clipboard, Toast.LENGTH_LONG).show(); + }); + + + } + + public static void showDisableBackupDialog(@NonNull Context context, @NonNull SwitchPreferenceCompat preference) { + new AlertDialog.Builder(context) + .setTitle(R.string.BackupDialog_delete_backups) + .setMessage(R.string.BackupDialog_disable_and_delete_all_local_backups) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.BackupDialog_delete_backups_statement, (dialog, which) -> { + TextSecurePreferences.setBackupPassphrase(context, null); + TextSecurePreferences.setBackupEnabled(context, false); + BackupUtil.deleteAllBackups(); + preference.setChecked(false); + }) + .create() + .show(); + } +} diff --git a/src/org/thoughtcrime/securesms/backup/BackupProtos.java b/src/org/thoughtcrime/securesms/backup/BackupProtos.java new file mode 100644 index 000000000..82ae671a4 --- /dev/null +++ b/src/org/thoughtcrime/securesms/backup/BackupProtos.java @@ -0,0 +1,4079 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: Backups.proto + +package org.thoughtcrime.securesms.backup; + +public final class BackupProtos { + private BackupProtos() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public interface SqlStatementOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional string statement = 1; + /** + * optional string statement = 1; + */ + boolean hasStatement(); + /** + * optional string statement = 1; + */ + java.lang.String getStatement(); + /** + * optional string statement = 1; + */ + com.google.protobuf.ByteString + getStatementBytes(); + } + /** + * Protobuf type {@code signal.SqlStatement} + */ + public static final class SqlStatement extends + com.google.protobuf.GeneratedMessage + implements SqlStatementOrBuilder { + // Use SqlStatement.newBuilder() to construct. + private SqlStatement(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private SqlStatement(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final SqlStatement defaultInstance; + public static SqlStatement getDefaultInstance() { + return defaultInstance; + } + + public SqlStatement getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private SqlStatement( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + statement_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public SqlStatement parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SqlStatement(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional string statement = 1; + public static final int STATEMENT_FIELD_NUMBER = 1; + private java.lang.Object statement_; + /** + * optional string statement = 1; + */ + public boolean hasStatement() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string statement = 1; + */ + public java.lang.String getStatement() { + java.lang.Object ref = statement_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + statement_ = s; + } + return s; + } + } + /** + * optional string statement = 1; + */ + public com.google.protobuf.ByteString + getStatementBytes() { + java.lang.Object ref = statement_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + statement_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private void initFields() { + statement_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getStatementBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, getStatementBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.SqlStatement} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + statement_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement build() { + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = new org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.statement_ = statement_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance()) return this; + if (other.hasStatement()) { + bitField0_ |= 0x00000001; + statement_ = other.statement_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional string statement = 1; + private java.lang.Object statement_ = ""; + /** + * optional string statement = 1; + */ + public boolean hasStatement() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string statement = 1; + */ + public java.lang.String getStatement() { + java.lang.Object ref = statement_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + statement_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string statement = 1; + */ + public com.google.protobuf.ByteString + getStatementBytes() { + java.lang.Object ref = statement_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + statement_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string statement = 1; + */ + public Builder setStatement( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + statement_ = value; + onChanged(); + return this; + } + /** + * optional string statement = 1; + */ + public Builder clearStatement() { + bitField0_ = (bitField0_ & ~0x00000001); + statement_ = getDefaultInstance().getStatement(); + onChanged(); + return this; + } + /** + * optional string statement = 1; + */ + public Builder setStatementBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + statement_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.SqlStatement) + } + + static { + defaultInstance = new SqlStatement(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.SqlStatement) + } + + public interface SharedPreferenceOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional string file = 1; + /** + * optional string file = 1; + */ + boolean hasFile(); + /** + * optional string file = 1; + */ + java.lang.String getFile(); + /** + * optional string file = 1; + */ + com.google.protobuf.ByteString + getFileBytes(); + + // optional string key = 2; + /** + * optional string key = 2; + */ + boolean hasKey(); + /** + * optional string key = 2; + */ + java.lang.String getKey(); + /** + * optional string key = 2; + */ + com.google.protobuf.ByteString + getKeyBytes(); + + // optional string value = 3; + /** + * optional string value = 3; + */ + boolean hasValue(); + /** + * optional string value = 3; + */ + java.lang.String getValue(); + /** + * optional string value = 3; + */ + com.google.protobuf.ByteString + getValueBytes(); + } + /** + * Protobuf type {@code signal.SharedPreference} + */ + public static final class SharedPreference extends + com.google.protobuf.GeneratedMessage + implements SharedPreferenceOrBuilder { + // Use SharedPreference.newBuilder() to construct. + private SharedPreference(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private SharedPreference(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final SharedPreference defaultInstance; + public static SharedPreference getDefaultInstance() { + return defaultInstance; + } + + public SharedPreference getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private SharedPreference( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + file_ = input.readBytes(); + break; + } + case 18: { + bitField0_ |= 0x00000002; + key_ = input.readBytes(); + break; + } + case 26: { + bitField0_ |= 0x00000004; + value_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public SharedPreference parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SharedPreference(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional string file = 1; + public static final int FILE_FIELD_NUMBER = 1; + private java.lang.Object file_; + /** + * optional string file = 1; + */ + public boolean hasFile() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string file = 1; + */ + public java.lang.String getFile() { + java.lang.Object ref = file_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + file_ = s; + } + return s; + } + } + /** + * optional string file = 1; + */ + public com.google.protobuf.ByteString + getFileBytes() { + java.lang.Object ref = file_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + file_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional string key = 2; + public static final int KEY_FIELD_NUMBER = 2; + private java.lang.Object key_; + /** + * optional string key = 2; + */ + public boolean hasKey() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string key = 2; + */ + public java.lang.String getKey() { + java.lang.Object ref = key_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + key_ = s; + } + return s; + } + } + /** + * optional string key = 2; + */ + public com.google.protobuf.ByteString + getKeyBytes() { + java.lang.Object ref = key_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + key_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + // optional string value = 3; + public static final int VALUE_FIELD_NUMBER = 3; + private java.lang.Object value_; + /** + * optional string value = 3; + */ + public boolean hasValue() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional string value = 3; + */ + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + value_ = s; + } + return s; + } + } + /** + * optional string value = 3; + */ + public com.google.protobuf.ByteString + getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private void initFields() { + file_ = ""; + key_ = ""; + value_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getFileBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, getKeyBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(3, getValueBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, getFileBytes()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, getKeyBytes()); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(3, getValueBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.SharedPreference} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + file_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + key_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + value_ = ""; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference build() { + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = new org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.file_ = file_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.key_ = key_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.value_ = value_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance()) return this; + if (other.hasFile()) { + bitField0_ |= 0x00000001; + file_ = other.file_; + onChanged(); + } + if (other.hasKey()) { + bitField0_ |= 0x00000002; + key_ = other.key_; + onChanged(); + } + if (other.hasValue()) { + bitField0_ |= 0x00000004; + value_ = other.value_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional string file = 1; + private java.lang.Object file_ = ""; + /** + * optional string file = 1; + */ + public boolean hasFile() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string file = 1; + */ + public java.lang.String getFile() { + java.lang.Object ref = file_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + file_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string file = 1; + */ + public com.google.protobuf.ByteString + getFileBytes() { + java.lang.Object ref = file_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + file_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string file = 1; + */ + public Builder setFile( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + file_ = value; + onChanged(); + return this; + } + /** + * optional string file = 1; + */ + public Builder clearFile() { + bitField0_ = (bitField0_ & ~0x00000001); + file_ = getDefaultInstance().getFile(); + onChanged(); + return this; + } + /** + * optional string file = 1; + */ + public Builder setFileBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + file_ = value; + onChanged(); + return this; + } + + // optional string key = 2; + private java.lang.Object key_ = ""; + /** + * optional string key = 2; + */ + public boolean hasKey() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string key = 2; + */ + public java.lang.String getKey() { + java.lang.Object ref = key_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + key_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string key = 2; + */ + public com.google.protobuf.ByteString + getKeyBytes() { + java.lang.Object ref = key_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + key_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string key = 2; + */ + public Builder setKey( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + key_ = value; + onChanged(); + return this; + } + /** + * optional string key = 2; + */ + public Builder clearKey() { + bitField0_ = (bitField0_ & ~0x00000002); + key_ = getDefaultInstance().getKey(); + onChanged(); + return this; + } + /** + * optional string key = 2; + */ + public Builder setKeyBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + key_ = value; + onChanged(); + return this; + } + + // optional string value = 3; + private java.lang.Object value_ = ""; + /** + * optional string value = 3; + */ + public boolean hasValue() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional string value = 3; + */ + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (!(ref instanceof java.lang.String)) { + java.lang.String s = ((com.google.protobuf.ByteString) ref) + .toStringUtf8(); + value_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string value = 3; + */ + public com.google.protobuf.ByteString + getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string value = 3; + */ + public Builder setValue( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + value_ = value; + onChanged(); + return this; + } + /** + * optional string value = 3; + */ + public Builder clearValue() { + bitField0_ = (bitField0_ & ~0x00000004); + value_ = getDefaultInstance().getValue(); + onChanged(); + return this; + } + /** + * optional string value = 3; + */ + public Builder setValueBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + value_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.SharedPreference) + } + + static { + defaultInstance = new SharedPreference(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.SharedPreference) + } + + public interface AttachmentOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional uint64 rowId = 1; + /** + * optional uint64 rowId = 1; + */ + boolean hasRowId(); + /** + * optional uint64 rowId = 1; + */ + long getRowId(); + + // optional uint64 attachmentId = 2; + /** + * optional uint64 attachmentId = 2; + */ + boolean hasAttachmentId(); + /** + * optional uint64 attachmentId = 2; + */ + long getAttachmentId(); + + // optional uint32 length = 3; + /** + * optional uint32 length = 3; + */ + boolean hasLength(); + /** + * optional uint32 length = 3; + */ + int getLength(); + } + /** + * Protobuf type {@code signal.Attachment} + */ + public static final class Attachment extends + com.google.protobuf.GeneratedMessage + implements AttachmentOrBuilder { + // Use Attachment.newBuilder() to construct. + private Attachment(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private Attachment(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final Attachment defaultInstance; + public static Attachment getDefaultInstance() { + return defaultInstance; + } + + public Attachment getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Attachment( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + bitField0_ |= 0x00000001; + rowId_ = input.readUInt64(); + break; + } + case 16: { + bitField0_ |= 0x00000002; + attachmentId_ = input.readUInt64(); + break; + } + case 24: { + bitField0_ |= 0x00000004; + length_ = input.readUInt32(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public Attachment parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Attachment(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional uint64 rowId = 1; + public static final int ROWID_FIELD_NUMBER = 1; + private long rowId_; + /** + * optional uint64 rowId = 1; + */ + public boolean hasRowId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional uint64 rowId = 1; + */ + public long getRowId() { + return rowId_; + } + + // optional uint64 attachmentId = 2; + public static final int ATTACHMENTID_FIELD_NUMBER = 2; + private long attachmentId_; + /** + * optional uint64 attachmentId = 2; + */ + public boolean hasAttachmentId() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional uint64 attachmentId = 2; + */ + public long getAttachmentId() { + return attachmentId_; + } + + // optional uint32 length = 3; + public static final int LENGTH_FIELD_NUMBER = 3; + private int length_; + /** + * optional uint32 length = 3; + */ + public boolean hasLength() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional uint32 length = 3; + */ + public int getLength() { + return length_; + } + + private void initFields() { + rowId_ = 0L; + attachmentId_ = 0L; + length_ = 0; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeUInt64(1, rowId_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeUInt64(2, attachmentId_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeUInt32(3, length_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(1, rowId_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(2, attachmentId_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(3, length_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Attachment prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.Attachment} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Attachment.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + rowId_ = 0L; + bitField0_ = (bitField0_ & ~0x00000001); + attachmentId_ = 0L; + bitField0_ = (bitField0_ & ~0x00000002); + length_ = 0; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment build() { + org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = new org.thoughtcrime.securesms.backup.BackupProtos.Attachment(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.rowId_ = rowId_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.attachmentId_ = attachmentId_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.length_ = length_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Attachment) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Attachment)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Attachment other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance()) return this; + if (other.hasRowId()) { + setRowId(other.getRowId()); + } + if (other.hasAttachmentId()) { + setAttachmentId(other.getAttachmentId()); + } + if (other.hasLength()) { + setLength(other.getLength()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.Attachment parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Attachment) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional uint64 rowId = 1; + private long rowId_ ; + /** + * optional uint64 rowId = 1; + */ + public boolean hasRowId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional uint64 rowId = 1; + */ + public long getRowId() { + return rowId_; + } + /** + * optional uint64 rowId = 1; + */ + public Builder setRowId(long value) { + bitField0_ |= 0x00000001; + rowId_ = value; + onChanged(); + return this; + } + /** + * optional uint64 rowId = 1; + */ + public Builder clearRowId() { + bitField0_ = (bitField0_ & ~0x00000001); + rowId_ = 0L; + onChanged(); + return this; + } + + // optional uint64 attachmentId = 2; + private long attachmentId_ ; + /** + * optional uint64 attachmentId = 2; + */ + public boolean hasAttachmentId() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional uint64 attachmentId = 2; + */ + public long getAttachmentId() { + return attachmentId_; + } + /** + * optional uint64 attachmentId = 2; + */ + public Builder setAttachmentId(long value) { + bitField0_ |= 0x00000002; + attachmentId_ = value; + onChanged(); + return this; + } + /** + * optional uint64 attachmentId = 2; + */ + public Builder clearAttachmentId() { + bitField0_ = (bitField0_ & ~0x00000002); + attachmentId_ = 0L; + onChanged(); + return this; + } + + // optional uint32 length = 3; + private int length_ ; + /** + * optional uint32 length = 3; + */ + public boolean hasLength() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional uint32 length = 3; + */ + public int getLength() { + return length_; + } + /** + * optional uint32 length = 3; + */ + public Builder setLength(int value) { + bitField0_ |= 0x00000004; + length_ = value; + onChanged(); + return this; + } + /** + * optional uint32 length = 3; + */ + public Builder clearLength() { + bitField0_ = (bitField0_ & ~0x00000004); + length_ = 0; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.Attachment) + } + + static { + defaultInstance = new Attachment(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.Attachment) + } + + public interface DatabaseVersionOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional uint32 version = 1; + /** + * optional uint32 version = 1; + */ + boolean hasVersion(); + /** + * optional uint32 version = 1; + */ + int getVersion(); + } + /** + * Protobuf type {@code signal.DatabaseVersion} + */ + public static final class DatabaseVersion extends + com.google.protobuf.GeneratedMessage + implements DatabaseVersionOrBuilder { + // Use DatabaseVersion.newBuilder() to construct. + private DatabaseVersion(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private DatabaseVersion(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final DatabaseVersion defaultInstance; + public static DatabaseVersion getDefaultInstance() { + return defaultInstance; + } + + public DatabaseVersion getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private DatabaseVersion( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + bitField0_ |= 0x00000001; + version_ = input.readUInt32(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public DatabaseVersion parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DatabaseVersion(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional uint32 version = 1; + public static final int VERSION_FIELD_NUMBER = 1; + private int version_; + /** + * optional uint32 version = 1; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional uint32 version = 1; + */ + public int getVersion() { + return version_; + } + + private void initFields() { + version_ = 0; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeUInt32(1, version_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt32Size(1, version_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.DatabaseVersion} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + version_ = 0; + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion build() { + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = new org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.version_ = version_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance()) return this; + if (other.hasVersion()) { + setVersion(other.getVersion()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional uint32 version = 1; + private int version_ ; + /** + * optional uint32 version = 1; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional uint32 version = 1; + */ + public int getVersion() { + return version_; + } + /** + * optional uint32 version = 1; + */ + public Builder setVersion(int value) { + bitField0_ |= 0x00000001; + version_ = value; + onChanged(); + return this; + } + /** + * optional uint32 version = 1; + */ + public Builder clearVersion() { + bitField0_ = (bitField0_ & ~0x00000001); + version_ = 0; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.DatabaseVersion) + } + + static { + defaultInstance = new DatabaseVersion(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.DatabaseVersion) + } + + public interface HeaderOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional bytes iv = 1; + /** + * optional bytes iv = 1; + */ + boolean hasIv(); + /** + * optional bytes iv = 1; + */ + com.google.protobuf.ByteString getIv(); + } + /** + * Protobuf type {@code signal.Header} + */ + public static final class Header extends + com.google.protobuf.GeneratedMessage + implements HeaderOrBuilder { + // Use Header.newBuilder() to construct. + private Header(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private Header(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final Header defaultInstance; + public static Header getDefaultInstance() { + return defaultInstance; + } + + public Header getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Header( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + bitField0_ |= 0x00000001; + iv_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.Header.class, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder.class); + } + + public static com.google.protobuf.Parser
PARSER = + new com.google.protobuf.AbstractParser
() { + public Header parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Header(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser
getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional bytes iv = 1; + public static final int IV_FIELD_NUMBER = 1; + private com.google.protobuf.ByteString iv_; + /** + * optional bytes iv = 1; + */ + public boolean hasIv() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional bytes iv = 1; + */ + public com.google.protobuf.ByteString getIv() { + return iv_; + } + + private void initFields() { + iv_ = com.google.protobuf.ByteString.EMPTY; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, iv_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, iv_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Header prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.Header} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.Header.class, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Header.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + iv_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Header getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Header build() { + org.thoughtcrime.securesms.backup.BackupProtos.Header result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.Header buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.Header result = new org.thoughtcrime.securesms.backup.BackupProtos.Header(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.iv_ = iv_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Header) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Header)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Header other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance()) return this; + if (other.hasIv()) { + setIv(other.getIv()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.Header parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Header) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional bytes iv = 1; + private com.google.protobuf.ByteString iv_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes iv = 1; + */ + public boolean hasIv() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional bytes iv = 1; + */ + public com.google.protobuf.ByteString getIv() { + return iv_; + } + /** + * optional bytes iv = 1; + */ + public Builder setIv(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + iv_ = value; + onChanged(); + return this; + } + /** + * optional bytes iv = 1; + */ + public Builder clearIv() { + bitField0_ = (bitField0_ & ~0x00000001); + iv_ = getDefaultInstance().getIv(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.Header) + } + + static { + defaultInstance = new Header(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.Header) + } + + public interface BackupFrameOrBuilder + extends com.google.protobuf.MessageOrBuilder { + + // optional .signal.Header header = 1; + /** + * optional .signal.Header header = 1; + */ + boolean hasHeader(); + /** + * optional .signal.Header header = 1; + */ + org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader(); + /** + * optional .signal.Header header = 1; + */ + org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder(); + + // optional .signal.SqlStatement statement = 2; + /** + * optional .signal.SqlStatement statement = 2; + */ + boolean hasStatement(); + /** + * optional .signal.SqlStatement statement = 2; + */ + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement(); + /** + * optional .signal.SqlStatement statement = 2; + */ + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder(); + + // optional .signal.SharedPreference preference = 3; + /** + * optional .signal.SharedPreference preference = 3; + */ + boolean hasPreference(); + /** + * optional .signal.SharedPreference preference = 3; + */ + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference(); + /** + * optional .signal.SharedPreference preference = 3; + */ + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder(); + + // optional .signal.Attachment attachment = 4; + /** + * optional .signal.Attachment attachment = 4; + */ + boolean hasAttachment(); + /** + * optional .signal.Attachment attachment = 4; + */ + org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment(); + /** + * optional .signal.Attachment attachment = 4; + */ + org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder(); + + // optional .signal.DatabaseVersion version = 5; + /** + * optional .signal.DatabaseVersion version = 5; + */ + boolean hasVersion(); + /** + * optional .signal.DatabaseVersion version = 5; + */ + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion(); + /** + * optional .signal.DatabaseVersion version = 5; + */ + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder(); + + // optional bool end = 6; + /** + * optional bool end = 6; + */ + boolean hasEnd(); + /** + * optional bool end = 6; + */ + boolean getEnd(); + } + /** + * Protobuf type {@code signal.BackupFrame} + */ + public static final class BackupFrame extends + com.google.protobuf.GeneratedMessage + implements BackupFrameOrBuilder { + // Use BackupFrame.newBuilder() to construct. + private BackupFrame(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private BackupFrame(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final BackupFrame defaultInstance; + public static BackupFrame getDefaultInstance() { + return defaultInstance; + } + + public BackupFrame getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private BackupFrame( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Header.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; + } + case 18: { + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder subBuilder = null; + if (((bitField0_ & 0x00000002) == 0x00000002)) { + subBuilder = statement_.toBuilder(); + } + statement_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(statement_); + statement_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000002; + break; + } + case 26: { + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder subBuilder = null; + if (((bitField0_ & 0x00000004) == 0x00000004)) { + subBuilder = preference_.toBuilder(); + } + preference_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(preference_); + preference_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000004; + break; + } + case 34: { + org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder subBuilder = null; + if (((bitField0_ & 0x00000008) == 0x00000008)) { + subBuilder = attachment_.toBuilder(); + } + attachment_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Attachment.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(attachment_); + attachment_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000008; + break; + } + case 42: { + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder subBuilder = null; + if (((bitField0_ & 0x00000010) == 0x00000010)) { + subBuilder = version_.toBuilder(); + } + version_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(version_); + version_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000010; + break; + } + case 48: { + bitField0_ |= 0x00000020; + end_ = input.readBool(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.class, org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public BackupFrame parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new BackupFrame(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + // optional .signal.Header header = 1; + public static final int HEADER_FIELD_NUMBER = 1; + private org.thoughtcrime.securesms.backup.BackupProtos.Header header_; + /** + * optional .signal.Header header = 1; + */ + public boolean hasHeader() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .signal.Header header = 1; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader() { + return header_; + } + /** + * optional .signal.Header header = 1; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder() { + return header_; + } + + // optional .signal.SqlStatement statement = 2; + public static final int STATEMENT_FIELD_NUMBER = 2; + private org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement statement_; + /** + * optional .signal.SqlStatement statement = 2; + */ + public boolean hasStatement() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement() { + return statement_; + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder() { + return statement_; + } + + // optional .signal.SharedPreference preference = 3; + public static final int PREFERENCE_FIELD_NUMBER = 3; + private org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference preference_; + /** + * optional .signal.SharedPreference preference = 3; + */ + public boolean hasPreference() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference() { + return preference_; + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder() { + return preference_; + } + + // optional .signal.Attachment attachment = 4; + public static final int ATTACHMENT_FIELD_NUMBER = 4; + private org.thoughtcrime.securesms.backup.BackupProtos.Attachment attachment_; + /** + * optional .signal.Attachment attachment = 4; + */ + public boolean hasAttachment() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional .signal.Attachment attachment = 4; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment() { + return attachment_; + } + /** + * optional .signal.Attachment attachment = 4; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder() { + return attachment_; + } + + // optional .signal.DatabaseVersion version = 5; + public static final int VERSION_FIELD_NUMBER = 5; + private org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion version_; + /** + * optional .signal.DatabaseVersion version = 5; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion() { + return version_; + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder() { + return version_; + } + + // optional bool end = 6; + public static final int END_FIELD_NUMBER = 6; + private boolean end_; + /** + * optional bool end = 6; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000020) == 0x00000020); + } + /** + * optional bool end = 6; + */ + public boolean getEnd() { + return end_; + } + + private void initFields() { + header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); + statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); + preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); + attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); + version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); + end_ = false; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized != -1) return isInitialized == 1; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeMessage(1, header_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeMessage(2, statement_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeMessage(3, preference_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeMessage(4, attachment_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + output.writeMessage(5, version_); + } + if (((bitField0_ & 0x00000020) == 0x00000020)) { + output.writeBool(6, end_); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, header_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, statement_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, preference_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, attachment_); + } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, version_); + } + if (((bitField0_ & 0x00000020) == 0x00000020)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(6, end_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code signal.BackupFrame} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder + implements org.thoughtcrime.securesms.backup.BackupProtos.BackupFrameOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.class, org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.Builder.class); + } + + // Construct using org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getHeaderFieldBuilder(); + getStatementFieldBuilder(); + getPreferenceFieldBuilder(); + getAttachmentFieldBuilder(); + getVersionFieldBuilder(); + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + if (headerBuilder_ == null) { + header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); + } else { + headerBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + if (statementBuilder_ == null) { + statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); + } else { + statementBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + if (preferenceBuilder_ == null) { + preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); + } else { + preferenceBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + if (attachmentBuilder_ == null) { + attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); + } else { + attachmentBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + if (versionBuilder_ == null) { + version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); + } else { + versionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000010); + end_ = false; + bitField0_ = (bitField0_ & ~0x00000020); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame getDefaultInstanceForType() { + return org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.getDefaultInstance(); + } + + public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame build() { + org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame buildPartial() { + org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame result = new org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + if (headerBuilder_ == null) { + result.header_ = header_; + } else { + result.header_ = headerBuilder_.build(); + } + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + if (statementBuilder_ == null) { + result.statement_ = statement_; + } else { + result.statement_ = statementBuilder_.build(); + } + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + if (preferenceBuilder_ == null) { + result.preference_ = preference_; + } else { + result.preference_ = preferenceBuilder_.build(); + } + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + if (attachmentBuilder_ == null) { + result.attachment_ = attachment_; + } else { + result.attachment_ = attachmentBuilder_.build(); + } + if (((from_bitField0_ & 0x00000010) == 0x00000010)) { + to_bitField0_ |= 0x00000010; + } + if (versionBuilder_ == null) { + result.version_ = version_; + } else { + result.version_ = versionBuilder_.build(); + } + if (((from_bitField0_ & 0x00000020) == 0x00000020)) { + to_bitField0_ |= 0x00000020; + } + result.end_ = end_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame) { + return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame other) { + if (other == org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.getDefaultInstance()) return this; + if (other.hasHeader()) { + mergeHeader(other.getHeader()); + } + if (other.hasStatement()) { + mergeStatement(other.getStatement()); + } + if (other.hasPreference()) { + mergePreference(other.getPreference()); + } + if (other.hasAttachment()) { + mergeAttachment(other.getAttachment()); + } + if (other.hasVersion()) { + mergeVersion(other.getVersion()); + } + if (other.hasEnd()) { + setEnd(other.getEnd()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + // optional .signal.Header header = 1; + private org.thoughtcrime.securesms.backup.BackupProtos.Header header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder> headerBuilder_; + /** + * optional .signal.Header header = 1; + */ + public boolean hasHeader() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .signal.Header header = 1; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader() { + if (headerBuilder_ == null) { + return header_; + } else { + return headerBuilder_.getMessage(); + } + } + /** + * optional .signal.Header header = 1; + */ + public Builder setHeader(org.thoughtcrime.securesms.backup.BackupProtos.Header value) { + if (headerBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + header_ = value; + onChanged(); + } else { + headerBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .signal.Header header = 1; + */ + public Builder setHeader( + org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder builderForValue) { + if (headerBuilder_ == null) { + header_ = builderForValue.build(); + onChanged(); + } else { + headerBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .signal.Header header = 1; + */ + public Builder mergeHeader(org.thoughtcrime.securesms.backup.BackupProtos.Header value) { + if (headerBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001) && + header_ != org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance()) { + header_ = + org.thoughtcrime.securesms.backup.BackupProtos.Header.newBuilder(header_).mergeFrom(value).buildPartial(); + } else { + header_ = value; + } + onChanged(); + } else { + headerBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .signal.Header header = 1; + */ + public Builder clearHeader() { + if (headerBuilder_ == null) { + header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); + onChanged(); + } else { + headerBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + /** + * optional .signal.Header header = 1; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder getHeaderBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getHeaderFieldBuilder().getBuilder(); + } + /** + * optional .signal.Header header = 1; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder() { + if (headerBuilder_ != null) { + return headerBuilder_.getMessageOrBuilder(); + } else { + return header_; + } + } + /** + * optional .signal.Header header = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder> + getHeaderFieldBuilder() { + if (headerBuilder_ == null) { + headerBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder>( + header_, + getParentForChildren(), + isClean()); + header_ = null; + } + return headerBuilder_; + } + + // optional .signal.SqlStatement statement = 2; + private org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder> statementBuilder_; + /** + * optional .signal.SqlStatement statement = 2; + */ + public boolean hasStatement() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement() { + if (statementBuilder_ == null) { + return statement_; + } else { + return statementBuilder_.getMessage(); + } + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public Builder setStatement(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement value) { + if (statementBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + statement_ = value; + onChanged(); + } else { + statementBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + return this; + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public Builder setStatement( + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder builderForValue) { + if (statementBuilder_ == null) { + statement_ = builderForValue.build(); + onChanged(); + } else { + statementBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + return this; + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public Builder mergeStatement(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement value) { + if (statementBuilder_ == null) { + if (((bitField0_ & 0x00000002) == 0x00000002) && + statement_ != org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance()) { + statement_ = + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.newBuilder(statement_).mergeFrom(value).buildPartial(); + } else { + statement_ = value; + } + onChanged(); + } else { + statementBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000002; + return this; + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public Builder clearStatement() { + if (statementBuilder_ == null) { + statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); + onChanged(); + } else { + statementBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder getStatementBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return getStatementFieldBuilder().getBuilder(); + } + /** + * optional .signal.SqlStatement statement = 2; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder() { + if (statementBuilder_ != null) { + return statementBuilder_.getMessageOrBuilder(); + } else { + return statement_; + } + } + /** + * optional .signal.SqlStatement statement = 2; + */ + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder> + getStatementFieldBuilder() { + if (statementBuilder_ == null) { + statementBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder>( + statement_, + getParentForChildren(), + isClean()); + statement_ = null; + } + return statementBuilder_; + } + + // optional .signal.SharedPreference preference = 3; + private org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder> preferenceBuilder_; + /** + * optional .signal.SharedPreference preference = 3; + */ + public boolean hasPreference() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference() { + if (preferenceBuilder_ == null) { + return preference_; + } else { + return preferenceBuilder_.getMessage(); + } + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public Builder setPreference(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference value) { + if (preferenceBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + preference_ = value; + onChanged(); + } else { + preferenceBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public Builder setPreference( + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder builderForValue) { + if (preferenceBuilder_ == null) { + preference_ = builderForValue.build(); + onChanged(); + } else { + preferenceBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public Builder mergePreference(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference value) { + if (preferenceBuilder_ == null) { + if (((bitField0_ & 0x00000004) == 0x00000004) && + preference_ != org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance()) { + preference_ = + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.newBuilder(preference_).mergeFrom(value).buildPartial(); + } else { + preference_ = value; + } + onChanged(); + } else { + preferenceBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000004; + return this; + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public Builder clearPreference() { + if (preferenceBuilder_ == null) { + preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); + onChanged(); + } else { + preferenceBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder getPreferenceBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getPreferenceFieldBuilder().getBuilder(); + } + /** + * optional .signal.SharedPreference preference = 3; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder() { + if (preferenceBuilder_ != null) { + return preferenceBuilder_.getMessageOrBuilder(); + } else { + return preference_; + } + } + /** + * optional .signal.SharedPreference preference = 3; + */ + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder> + getPreferenceFieldBuilder() { + if (preferenceBuilder_ == null) { + preferenceBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder>( + preference_, + getParentForChildren(), + isClean()); + preference_ = null; + } + return preferenceBuilder_; + } + + // optional .signal.Attachment attachment = 4; + private org.thoughtcrime.securesms.backup.BackupProtos.Attachment attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder> attachmentBuilder_; + /** + * optional .signal.Attachment attachment = 4; + */ + public boolean hasAttachment() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional .signal.Attachment attachment = 4; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment() { + if (attachmentBuilder_ == null) { + return attachment_; + } else { + return attachmentBuilder_.getMessage(); + } + } + /** + * optional .signal.Attachment attachment = 4; + */ + public Builder setAttachment(org.thoughtcrime.securesms.backup.BackupProtos.Attachment value) { + if (attachmentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + attachment_ = value; + onChanged(); + } else { + attachmentBuilder_.setMessage(value); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .signal.Attachment attachment = 4; + */ + public Builder setAttachment( + org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder builderForValue) { + if (attachmentBuilder_ == null) { + attachment_ = builderForValue.build(); + onChanged(); + } else { + attachmentBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .signal.Attachment attachment = 4; + */ + public Builder mergeAttachment(org.thoughtcrime.securesms.backup.BackupProtos.Attachment value) { + if (attachmentBuilder_ == null) { + if (((bitField0_ & 0x00000008) == 0x00000008) && + attachment_ != org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance()) { + attachment_ = + org.thoughtcrime.securesms.backup.BackupProtos.Attachment.newBuilder(attachment_).mergeFrom(value).buildPartial(); + } else { + attachment_ = value; + } + onChanged(); + } else { + attachmentBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000008; + return this; + } + /** + * optional .signal.Attachment attachment = 4; + */ + public Builder clearAttachment() { + if (attachmentBuilder_ == null) { + attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); + onChanged(); + } else { + attachmentBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + /** + * optional .signal.Attachment attachment = 4; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder getAttachmentBuilder() { + bitField0_ |= 0x00000008; + onChanged(); + return getAttachmentFieldBuilder().getBuilder(); + } + /** + * optional .signal.Attachment attachment = 4; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder() { + if (attachmentBuilder_ != null) { + return attachmentBuilder_.getMessageOrBuilder(); + } else { + return attachment_; + } + } + /** + * optional .signal.Attachment attachment = 4; + */ + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder> + getAttachmentFieldBuilder() { + if (attachmentBuilder_ == null) { + attachmentBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder>( + attachment_, + getParentForChildren(), + isClean()); + attachment_ = null; + } + return attachmentBuilder_; + } + + // optional .signal.DatabaseVersion version = 5; + private org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder> versionBuilder_; + /** + * optional .signal.DatabaseVersion version = 5; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion() { + if (versionBuilder_ == null) { + return version_; + } else { + return versionBuilder_.getMessage(); + } + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public Builder setVersion(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion value) { + if (versionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + version_ = value; + onChanged(); + } else { + versionBuilder_.setMessage(value); + } + bitField0_ |= 0x00000010; + return this; + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public Builder setVersion( + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder builderForValue) { + if (versionBuilder_ == null) { + version_ = builderForValue.build(); + onChanged(); + } else { + versionBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000010; + return this; + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public Builder mergeVersion(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion value) { + if (versionBuilder_ == null) { + if (((bitField0_ & 0x00000010) == 0x00000010) && + version_ != org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance()) { + version_ = + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.newBuilder(version_).mergeFrom(value).buildPartial(); + } else { + version_ = value; + } + onChanged(); + } else { + versionBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000010; + return this; + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public Builder clearVersion() { + if (versionBuilder_ == null) { + version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); + onChanged(); + } else { + versionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000010); + return this; + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder getVersionBuilder() { + bitField0_ |= 0x00000010; + onChanged(); + return getVersionFieldBuilder().getBuilder(); + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder() { + if (versionBuilder_ != null) { + return versionBuilder_.getMessageOrBuilder(); + } else { + return version_; + } + } + /** + * optional .signal.DatabaseVersion version = 5; + */ + private com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder> + getVersionFieldBuilder() { + if (versionBuilder_ == null) { + versionBuilder_ = new com.google.protobuf.SingleFieldBuilder< + org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder>( + version_, + getParentForChildren(), + isClean()); + version_ = null; + } + return versionBuilder_; + } + + // optional bool end = 6; + private boolean end_ ; + /** + * optional bool end = 6; + */ + public boolean hasEnd() { + return ((bitField0_ & 0x00000020) == 0x00000020); + } + /** + * optional bool end = 6; + */ + public boolean getEnd() { + return end_; + } + /** + * optional bool end = 6; + */ + public Builder setEnd(boolean value) { + bitField0_ |= 0x00000020; + end_ = value; + onChanged(); + return this; + } + /** + * optional bool end = 6; + */ + public Builder clearEnd() { + bitField0_ = (bitField0_ & ~0x00000020); + end_ = false; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:signal.BackupFrame) + } + + static { + defaultInstance = new BackupFrame(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:signal.BackupFrame) + } + + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_SqlStatement_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_SqlStatement_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_SharedPreference_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_SharedPreference_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_Attachment_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_Attachment_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_DatabaseVersion_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_DatabaseVersion_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_Header_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_Header_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_signal_BackupFrame_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_signal_BackupFrame_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\rBackups.proto\022\006signal\"!\n\014SqlStatement\022" + + "\021\n\tstatement\030\001 \001(\t\"<\n\020SharedPreference\022\014" + + "\n\004file\030\001 \001(\t\022\013\n\003key\030\002 \001(\t\022\r\n\005value\030\003 \001(\t" + + "\"A\n\nAttachment\022\r\n\005rowId\030\001 \001(\004\022\024\n\014attachm" + + "entId\030\002 \001(\004\022\016\n\006length\030\003 \001(\r\"\"\n\017DatabaseV" + + "ersion\022\017\n\007version\030\001 \001(\r\"\024\n\006Header\022\n\n\002iv\030" + + "\001 \001(\014\"\343\001\n\013BackupFrame\022\036\n\006header\030\001 \001(\0132\016." + + "signal.Header\022\'\n\tstatement\030\002 \001(\0132\024.signa" + + "l.SqlStatement\022,\n\npreference\030\003 \001(\0132\030.sig" + + "nal.SharedPreference\022&\n\nattachment\030\004 \001(\013", + "2\022.signal.Attachment\022(\n\007version\030\005 \001(\0132\027." + + "signal.DatabaseVersion\022\013\n\003end\030\006 \001(\010B1\n!o" + + "rg.thoughtcrime.securesms.backupB\014Backup" + + "Protos" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + internal_static_signal_SqlStatement_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_signal_SqlStatement_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_SqlStatement_descriptor, + new java.lang.String[] { "Statement", }); + internal_static_signal_SharedPreference_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_signal_SharedPreference_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_SharedPreference_descriptor, + new java.lang.String[] { "File", "Key", "Value", }); + internal_static_signal_Attachment_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_signal_Attachment_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_Attachment_descriptor, + new java.lang.String[] { "RowId", "AttachmentId", "Length", }); + internal_static_signal_DatabaseVersion_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_signal_DatabaseVersion_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_DatabaseVersion_descriptor, + new java.lang.String[] { "Version", }); + internal_static_signal_Header_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_signal_Header_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_Header_descriptor, + new java.lang.String[] { "Iv", }); + internal_static_signal_BackupFrame_descriptor = + getDescriptor().getMessageTypes().get(5); + internal_static_signal_BackupFrame_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_signal_BackupFrame_descriptor, + new java.lang.String[] { "Header", "Statement", "Preference", "Attachment", "Version", "End", }); + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupBase.java b/src/org/thoughtcrime/securesms/backup/FullBackupBase.java new file mode 100644 index 000000000..de475436b --- /dev/null +++ b/src/org/thoughtcrime/securesms/backup/FullBackupBase.java @@ -0,0 +1,62 @@ +package org.thoughtcrime.securesms.backup; + + +import android.support.annotation.NonNull; +import android.util.Log; + +import org.greenrobot.eventbus.EventBus; +import org.whispersystems.libsignal.util.ByteUtil; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public abstract class FullBackupBase { + + private static final String TAG = FullBackupBase.class.getSimpleName(); + + protected static @NonNull byte[] getBackupKey(@NonNull String passphrase) { + try { + EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, 0)); + + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + byte[] input = passphrase.replace(" ", "").getBytes(); + byte[] hash = input; + + long start = System.currentTimeMillis(); + for (int i=0;i<250000;i++) { + if (i % 1000 == 0) EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, 0)); + digest.update(hash); + hash = digest.digest(input); + } + Log.w(TAG, "Generated: " + (System.currentTimeMillis()- start)); + + return ByteUtil.trim(hash, 32); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + public static class BackupEvent { + public enum Type { + PROGRESS, + FINISHED + } + + private final Type type; + private final int count; + + BackupEvent(Type type, int count) { + this.type = type; + this.count = count; + } + + public Type getType() { + return type; + } + + public int getCount() { + return count; + } + } + +} diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java b/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java new file mode 100644 index 000000000..a5e90a196 --- /dev/null +++ b/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java @@ -0,0 +1,312 @@ +package org.thoughtcrime.securesms.backup; + + +import android.content.Context; +import android.database.Cursor; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; + +import com.annimon.stream.function.Consumer; +import com.annimon.stream.function.Predicate; +import com.google.protobuf.ByteString; + +import net.sqlcipher.database.SQLiteDatabase; + +import org.greenrobot.eventbus.EventBus; +import org.thoughtcrime.securesms.attachments.AttachmentId; +import org.thoughtcrime.securesms.crypto.AttachmentSecret; +import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; +import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; +import org.thoughtcrime.securesms.database.AttachmentDatabase; +import org.thoughtcrime.securesms.database.MmsDatabase; +import org.thoughtcrime.securesms.database.MmsSmsColumns; +import org.thoughtcrime.securesms.database.OneTimePreKeyDatabase; +import org.thoughtcrime.securesms.database.SessionDatabase; +import org.thoughtcrime.securesms.database.SignedPreKeyDatabase; +import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.util.Conversions; +import org.thoughtcrime.securesms.util.Hex; +import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.libsignal.kdf.HKDFv3; +import org.whispersystems.libsignal.util.ByteUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.LinkedList; +import java.util.List; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +public class FullBackupExporter extends FullBackupBase { + + @SuppressWarnings("unused") + private static final String TAG = FullBackupExporter.class.getSimpleName(); + + public static void export(@NonNull Context context, + @NonNull AttachmentSecret attachmentSecret, + @NonNull SQLiteDatabase input, + @NonNull File output, + @NonNull String passphrase) + throws IOException + { + byte[] key = getBackupKey(passphrase); + BackupFrameOutputStream outputStream = new BackupFrameOutputStream(output, key); + outputStream.writeDatabaseVersion(input.getVersion()); + + List tables = exportSchema(input, outputStream); + int count = 0; + + for (String table : tables) { + if (table.equals(SmsDatabase.TABLE_NAME) || table.equals(MmsDatabase.TABLE_NAME)) { + count = exportTable(table, input, outputStream, cursor -> cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.EXPIRES_IN)) <= 0, null, count); + } else if (table.equals(AttachmentDatabase.TABLE_NAME)) { + count = exportTable(table, input, outputStream, null, cursor -> exportAttachment(attachmentSecret, cursor, outputStream), count); + } else if (!table.equals(SignedPreKeyDatabase.TABLE_NAME) && + !table.equals(OneTimePreKeyDatabase.TABLE_NAME) && + !table.equals(SessionDatabase.TABLE_NAME)) + { + count = exportTable(table, input, outputStream, null, null, count); + } + } + + for (BackupProtos.SharedPreference preference : IdentityKeyUtil.getBackupRecord(context)) { + if (++count % 100 == 0) EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, count)); + outputStream.write(preference); + } + + outputStream.writeEnd(); + outputStream.close(); + EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.FINISHED, count)); + } + + private static List exportSchema(@NonNull SQLiteDatabase input, @NonNull BackupFrameOutputStream outputStream) + throws IOException + { + List tables = new LinkedList<>(); + + try (Cursor cursor = input.rawQuery("SELECT sql, name, type FROM sqlite_master", null)) { + while (cursor != null && cursor.moveToNext()) { + String sql = cursor.getString(0); + String name = cursor.getString(1); + String type = cursor.getString(2); + + if (sql != null) { + if ("table".equals(type)) { + outputStream.write(BackupProtos.SqlStatement.newBuilder().setStatement("DROP TABLE IF EXISTS " + name).build()); + tables.add(name); + } else if ("index".equals(type)) { + outputStream.write(BackupProtos.SqlStatement.newBuilder().setStatement("DROP INDEX IF EXISTS " + name).build()); + } + + outputStream.write(BackupProtos.SqlStatement.newBuilder().setStatement(cursor.getString(0)).build()); + } + } + } + + return tables; + } + + private static int exportTable(@NonNull String table, + @NonNull SQLiteDatabase input, + @NonNull BackupFrameOutputStream outputStream, + @Nullable Predicate predicate, + @Nullable Consumer postProcess, + int count) + throws IOException + { + String template = "INSERT INTO " + table + " VALUES "; + + try (Cursor cursor = input.rawQuery("SELECT * FROM " + table, null)) { + while (cursor != null && cursor.moveToNext()) { + if (++count % 100 == 0) EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, count)); + + if (predicate == null || predicate.test(cursor)) { + StringBuilder statement = new StringBuilder(template); + + statement.append('('); + + for (int i=0;i output = ModernEncryptingPartOutputStream.createFor(attachmentSecret, dataFile, false); + + inputStream.readAttachmentTo(output.second, attachment.getLength()); + + ContentValues contentValues = new ContentValues(); + contentValues.put(AttachmentDatabase.DATA, dataFile.getAbsolutePath()); + contentValues.put(AttachmentDatabase.THUMBNAIL, (String)null); + contentValues.put(AttachmentDatabase.DATA_RANDOM, output.first); + + db.update(AttachmentDatabase.TABLE_NAME, contentValues, + AttachmentDatabase.ROW_ID + " = ? AND " + AttachmentDatabase.UNIQUE_ID + " = ?", + new String[] {String.valueOf(attachment.getRowId()), String.valueOf(attachment.getAttachmentId())}); + } + + @SuppressLint("ApplySharedPref") + private static void processPreference(@NonNull Context context, SharedPreference preference) { + SharedPreferences preferences = context.getSharedPreferences(preference.getFile(), 0); + preferences.edit().putString(preference.getKey(), preference.getValue()).commit(); + } + + private static class BackupRecordInputStream { + + private final InputStream in; + private final Cipher cipher; + private final Mac mac; + + private final byte[] cipherKey; + private final byte[] macKey; + + private byte[] iv; + private int counter; + + private BackupRecordInputStream(@NonNull File file, @NonNull byte[] key) throws IOException { + try { + byte[] derived = new HKDFv3().deriveSecrets(key, "Backup Export".getBytes(), 64); + byte[][] split = ByteUtil.split(derived, 32, 32); + + this.cipherKey = split[0]; + this.macKey = split[1]; + + this.cipher = Cipher.getInstance("AES/CTR/NoPadding"); + this.mac = Mac.getInstance("HmacSHA256"); + this.in = new FileInputStream(file); + this.mac.init(new SecretKeySpec(macKey, "HmacSHA256")); + + byte[] headerLengthBytes = new byte[4]; + Util.readFully(in, headerLengthBytes); + + int headerLength = Conversions.byteArrayToInt(headerLengthBytes); + byte[] headerFrame = new byte[headerLength]; + Util.readFully(in, headerFrame); + + BackupFrame frame = BackupFrame.parseFrom(headerFrame); + + if (!frame.hasHeader()) { + throw new IOException("Backup stream does not start with header!"); + } + + BackupProtos.Header header = frame.getHeader(); + + this.iv = header.getIv().toByteArray(); + + if (iv.length != 16) { + throw new IOException("Invalid IV length!"); + } + + this.counter = Conversions.byteArrayToInt(iv); + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) { + throw new AssertionError(e); + } + } + + BackupFrame readFrame() throws IOException { + return readFrame(in); + } + + void readAttachmentTo(OutputStream out, int length) throws IOException { + try { + Conversions.intToByteArray(iv, 0, counter++); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv)); + + byte[] buffer = new byte[8192]; + + while (length > 0) { + int read = in.read(buffer, 0, Math.min(buffer.length, length)); + if (read == -1) throw new IOException("File ended early!"); + + mac.update(buffer, 0, read); + + byte[] plaintext = cipher.update(buffer, 0, read); + out.write(plaintext, 0, plaintext.length); + + length -= read; + } + + out.close(); + + byte[] ourMac = mac.doFinal(); + byte[] theirMac = new byte[10]; + + try { + Util.readFully(in, theirMac); + } catch (IOException e) { + //destination.delete(); + throw new IOException(e); + } + + if (MessageDigest.isEqual(ourMac, theirMac)) { + //destination.delete(); + throw new IOException("Bad MAC"); + } + } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { + throw new AssertionError(e); + } + } + + private BackupFrame readFrame(InputStream in) throws IOException { + try { + byte[] length = new byte[4]; + Util.readFully(in, length); + + byte[] frame = new byte[Conversions.byteArrayToInt(length)]; + Util.readFully(in, frame); + + byte[] theirMac = new byte[10]; + System.arraycopy(frame, frame.length - 10, theirMac, 0, theirMac.length); + + mac.update(frame, 0, frame.length - 10); + byte[] ourMac = mac.doFinal(); + + if (MessageDigest.isEqual(ourMac, theirMac)) { + throw new IOException("Bad MAC"); + } + + Conversions.intToByteArray(iv, 0, counter++); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv)); + + byte[] plaintext = cipher.doFinal(frame, 0, frame.length - 10); + + return BackupFrame.parseFrom(plaintext); + } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { + throw new AssertionError(e); + } + } + } + +} diff --git a/src/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java b/src/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java index 2e7c4539d..77f2a1a17 100644 --- a/src/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java +++ b/src/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java @@ -4,12 +4,16 @@ import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.support.v7.preference.CheckBoxPreference; +import android.support.v7.preference.Preference; import android.util.AttributeSet; +import android.view.View; import org.thoughtcrime.securesms.R; public class SwitchPreferenceCompat extends CheckBoxPreference { + private Preference.OnPreferenceClickListener listener; + public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setLayoutRes(); @@ -34,4 +38,16 @@ public class SwitchPreferenceCompat extends CheckBoxPreference { private void setLayoutRes() { setWidgetLayoutResource(R.layout.switch_compat_preference); } + + @Override + public void setOnPreferenceClickListener(Preference.OnPreferenceClickListener listener) { + this.listener = listener; + } + + @Override + protected void onClick() { + if (listener == null || !listener.onPreferenceClick(this)) { + super.onClick(); + } + } } diff --git a/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index f7a9bb6d8..910d84709 100644 --- a/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Whisper Systems * Copyright (C) 2013 Open Whisper Systems * @@ -22,6 +22,7 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.support.annotation.NonNull; +import org.thoughtcrime.securesms.backup.BackupProtos; import org.thoughtcrime.securesms.util.Base64; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; @@ -31,6 +32,8 @@ import org.whispersystems.libsignal.ecc.ECKeyPair; import org.whispersystems.libsignal.ecc.ECPrivateKey; import java.io.IOException; +import java.util.LinkedList; +import java.util.List; /** * Utility class for working with identity keys. @@ -40,6 +43,7 @@ import java.io.IOException; public class IdentityKeyUtil { + @SuppressWarnings("unused") private static final String TAG = IdentityKeyUtil.class.getSimpleName(); private static final String IDENTITY_PUBLIC_KEY_CIPHERTEXT_LEGACY_PREF = "pref_identity_public_curve25519"; @@ -107,6 +111,23 @@ public class IdentityKeyUtil { } } + public static List getBackupRecord(@NonNull Context context) { + SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0); + + return new LinkedList() {{ + add(BackupProtos.SharedPreference.newBuilder() + .setFile(MasterSecretUtil.PREFERENCES_NAME) + .setKey(IDENTITY_PUBLIC_KEY_PREF) + .setValue(preferences.getString(IDENTITY_PUBLIC_KEY_PREF, null)) + .build()); + add(BackupProtos.SharedPreference.newBuilder() + .setFile(MasterSecretUtil.PREFERENCES_NAME) + .setKey(IDENTITY_PRIVATE_KEY_PREF) + .setValue(preferences.getString(IDENTITY_PRIVATE_KEY_PREF, null)) + .build()); + }}; + } + private static boolean hasLegacyIdentityKeys(Context context) { return retrieve(context, IDENTITY_PUBLIC_KEY_CIPHERTEXT_LEGACY_PREF) != null && diff --git a/src/org/thoughtcrime/securesms/database/AttachmentDatabase.java b/src/org/thoughtcrime/securesms/database/AttachmentDatabase.java index bce726012..f029babe1 100644 --- a/src/org/thoughtcrime/securesms/database/AttachmentDatabase.java +++ b/src/org/thoughtcrime/securesms/database/AttachmentDatabase.java @@ -65,27 +65,29 @@ public class AttachmentDatabase extends Database { private static final String TAG = AttachmentDatabase.class.getSimpleName(); - static final String TABLE_NAME = "part"; - static final String ROW_ID = "_id"; + public static final String TABLE_NAME = "part"; + public static final String ROW_ID = "_id"; public static final String ATTACHMENT_ID_ALIAS = "attachment_id"; static final String MMS_ID = "mid"; static final String CONTENT_TYPE = "ct"; static final String NAME = "name"; static final String CONTENT_DISPOSITION = "cd"; static final String CONTENT_LOCATION = "cl"; - static final String DATA = "_data"; + public static final String DATA = "_data"; static final String TRANSFER_STATE = "pending_push"; - static final String SIZE = "data_size"; + public static final String SIZE = "data_size"; static final String FILE_NAME = "file_name"; - static final String THUMBNAIL = "thumbnail"; + public static final String THUMBNAIL = "thumbnail"; static final String THUMBNAIL_ASPECT_RATIO = "aspect_ratio"; public static final String UNIQUE_ID = "unique_id"; static final String DIGEST = "digest"; static final String VOICE_NOTE = "voice_note"; public static final String FAST_PREFLIGHT_ID = "fast_preflight_id"; - private static final String DATA_RANDOM = "data_random"; + public static final String DATA_RANDOM = "data_random"; private static final String THUMBNAIL_RANDOM = "thumbnail_random"; + public static final String DIRECTORY = "parts"; + public static final int TRANSFER_PROGRESS_DONE = 0; public static final int TRANSFER_PROGRESS_STARTED = 1; public static final int TRANSFER_PROGRESS_PENDING = 2; @@ -256,7 +258,7 @@ public class AttachmentDatabase extends Database { SQLiteDatabase database = databaseHelper.getWritableDatabase(); database.delete(TABLE_NAME, null, null); - File attachmentsDirectory = context.getDir("parts", Context.MODE_PRIVATE); + File attachmentsDirectory = context.getDir(DIRECTORY, Context.MODE_PRIVATE); File[] attachments = attachmentsDirectory.listFiles(); for (File attachment : attachments) { @@ -459,7 +461,7 @@ public class AttachmentDatabase extends Database { throws MmsException { try { - File partsDirectory = context.getDir("parts", Context.MODE_PRIVATE); + File partsDirectory = context.getDir(DIRECTORY, Context.MODE_PRIVATE); File dataFile = File.createTempFile("part", ".mms", partsDirectory); return setAttachmentData(dataFile, in); } catch (IOException e) { diff --git a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java index 0937e7244..dded639ec 100644 --- a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -130,6 +130,14 @@ public class DatabaseFactory { return getInstance(context).sessionDatabase; } + public static SQLiteDatabase getBackupDatabase(Context context) { + return getInstance(context).databaseHelper.getReadableDatabase(); + } + + public static void upgradeRestored(Context context, SQLiteDatabase database){ + getInstance(context).databaseHelper.onUpgrade(database, database.getVersion(), -1); + } + private DatabaseFactory(@NonNull Context context) { SQLiteDatabase.loadLibs(context); diff --git a/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java b/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java deleted file mode 100644 index 7d04fa55f..000000000 --- a/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.thoughtcrime.securesms.database; - - -import android.content.Context; - -import org.thoughtcrime.securesms.database.model.SmsMessageRecord; -import org.thoughtcrime.securesms.util.StorageUtil; - -import java.io.File; -import java.io.IOException; - -public class PlaintextBackupExporter { - - private static final String FILENAME = "SignalPlaintextBackup.xml"; - - public static void exportPlaintextToSd(Context context) - throws NoExternalStorageException, IOException - { - exportPlaintext(context); - } - - public static File getPlaintextExportFile() throws NoExternalStorageException { - return new File(StorageUtil.getBackupDir(), FILENAME); - } - - private static void exportPlaintext(Context context) - throws NoExternalStorageException, IOException - { - SmsDatabase database = DatabaseFactory.getSmsDatabase(context); - int count = database.getMessageCount(); - XmlBackup.Writer writer = new XmlBackup.Writer(getPlaintextExportFile().getAbsolutePath(), count); - - - SmsMessageRecord record; - - SmsDatabase.Reader reader = null; - int skip = 0; - int ROW_LIMIT = 500; - - do { - if (reader != null) - reader.close(); - - reader = database.readerFor(database.getMessages(skip, ROW_LIMIT)); - - while ((record = reader.getNext()) != null) { - XmlBackup.XmlBackupItem item = - new XmlBackup.XmlBackupItem(0, record.getIndividualRecipient().getAddress().serialize(), - record.getIndividualRecipient().getName(), - record.getDateReceived(), - MmsSmsColumns.Types.translateToSystemBaseType(record.getType()), - null, record.getDisplayBody().toString(), null, - 1, record.getDeliveryStatus()); - - writer.writeItem(item); - } - - skip += ROW_LIMIT; - } while (reader.getCount() > 0); - - writer.close(); - } -} diff --git a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java index 538e370c4..3b8b357b6 100644 --- a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java +++ b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java @@ -8,6 +8,7 @@ import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteStatement; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.StorageUtil; import org.xmlpull.v1.XmlPullParserException; import java.io.File; @@ -72,7 +73,7 @@ public class PlaintextBackupImporter { } private static File getPlaintextExportFile() throws NoExternalStorageException { - File backup = PlaintextBackupExporter.getPlaintextExportFile(); + File backup = new File(StorageUtil.getLegacyBackupDirectory(), "SignalPlaintextBackup.xml"); File oldBackup = new File(Environment.getExternalStorageDirectory(), "TextSecurePlaintextBackup.xml"); return !backup.exists() && oldBackup.exists() ? oldBackup : backup; diff --git a/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java new file mode 100644 index 000000000..6fcf5a576 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java @@ -0,0 +1,94 @@ +package org.thoughtcrime.securesms.jobs; + + +import android.Manifest; +import android.content.Context; +import android.support.annotation.NonNull; +import android.util.Log; + +import org.thoughtcrime.securesms.backup.FullBackupExporter; +import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider; +import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.database.NoExternalStorageException; +import org.thoughtcrime.securesms.permissions.Permissions; +import org.thoughtcrime.securesms.service.GenericForegroundService; +import org.thoughtcrime.securesms.util.BackupUtil; +import org.thoughtcrime.securesms.util.StorageUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.whispersystems.jobqueue.JobParameters; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +public class LocalBackupJob extends ContextJob { + + private static final String TAG = LocalBackupJob.class.getSimpleName(); + + public LocalBackupJob(@NonNull Context context) { + super(context, JobParameters.newBuilder() + .withGroupId("__LOCAL_BACKUP__") + .withWakeLock(true, 10, TimeUnit.SECONDS) + .create()); + } + + @Override + public void onAdded() {} + + @Override + public void onRun() throws NoExternalStorageException, IOException { + Log.w(TAG, "Executing backup job..."); + + if (!Permissions.hasAll(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + throw new IOException("No external storage permission!"); + } + + GenericForegroundService.startForegroundTask(context, "Creating backup"); + + try { + String backupPassword = TextSecurePreferences.getBackupPassphrase(context); + File backupDirectory = StorageUtil.getBackupDirectory(); + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(new Date()); + String fileName = String.format("signal-%s.backup", timestamp); + File backupFile = new File(backupDirectory, fileName); + + if (backupFile.exists()) { + throw new IOException("Backup file already exists?"); + } + + if (backupPassword == null) { + throw new IOException("Backup password is null"); + } + + File tempFile = File.createTempFile("backup", "tmp", context.getExternalCacheDir()); + + FullBackupExporter.export(context, + AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret(), + DatabaseFactory.getBackupDatabase(context), + tempFile, + backupPassword); + + if (!tempFile.renameTo(backupFile)) { + tempFile.delete(); + throw new IOException("Renaming temporary backup file failed!"); + } + + BackupUtil.deleteOldBackups(); + } finally { + GenericForegroundService.stopForegroundTask(context); + } + } + + @Override + public boolean onShouldRetry(Exception e) { + return false; + } + + @Override + public void onCanceled() { + + } +} diff --git a/src/org/thoughtcrime/securesms/mms/ImageSlide.java b/src/org/thoughtcrime/securesms/mms/ImageSlide.java index 6c05af8af..8ce4ec52f 100644 --- a/src/org/thoughtcrime/securesms/mms/ImageSlide.java +++ b/src/org/thoughtcrime/securesms/mms/ImageSlide.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (C) 2011 Whisper Systems * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ import android.content.res.Resources.Theme; import android.net.Uri; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.attachments.Attachment; @@ -28,6 +29,7 @@ import org.thoughtcrime.securesms.util.MediaUtil; public class ImageSlide extends Slide { + @SuppressWarnings("unused") private static final String TAG = ImageSlide.class.getSimpleName(); public ImageSlide(@NonNull Context context, @NonNull Attachment attachment) { @@ -43,6 +45,14 @@ public class ImageSlide extends Slide { return 0; } + @Override + public @Nullable Uri getThumbnailUri() { + Uri thumbnailUri = super.getThumbnailUri(); + + if (thumbnailUri == null) return getUri(); + else return thumbnailUri; + } + @Override public boolean hasImage() { return true; diff --git a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java index f04c2d640..812e38b22 100644 --- a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java @@ -223,7 +223,7 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment { Intent nextIntent = new Intent(getActivity(), ApplicationPreferencesActivity.class); Intent intent = new Intent(getActivity(), RegistrationActivity.class); - intent.putExtra("cancel_button", true); + intent.putExtra(RegistrationActivity.RE_REGISTRATION_EXTRA, true); intent.putExtra("next_intent", nextIntent); startActivity(intent); } diff --git a/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java index 3e890af87..cadeda527 100644 --- a/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java @@ -1,8 +1,11 @@ package org.thoughtcrime.securesms.preferences; +import android.Manifest; +import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.support.v7.preference.EditTextPreference; @@ -11,13 +14,26 @@ import android.support.v7.preference.Preference; import android.text.TextUtils; import android.util.Log; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationPreferencesActivity; import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.backup.BackupDialog; +import org.thoughtcrime.securesms.backup.FullBackupBase; +import org.thoughtcrime.securesms.backup.FullBackupBase.BackupEvent; +import org.thoughtcrime.securesms.components.SwitchPreferenceCompat; +import org.thoughtcrime.securesms.jobs.LocalBackupJob; +import org.thoughtcrime.securesms.permissions.Permissions; +import org.thoughtcrime.securesms.preferences.widgets.ProgressPreference; +import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Trimmer; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Set; public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment { @@ -41,7 +57,14 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment { findPreference(TextSecurePreferences.THREAD_TRIM_LENGTH) .setOnPreferenceChangeListener(new TrimLengthValidationListener()); + findPreference(TextSecurePreferences.BACKUP_ENABLED) + .setOnPreferenceClickListener(new BackupClickListener()); + findPreference(TextSecurePreferences.BACKUP_NOW) + .setOnPreferenceClickListener(new BackupCreateListener()); + initializeListSummary((ListPreference) findPreference(TextSecurePreferences.MESSAGE_BODY_TEXT_SIZE_PREF)); + + EventBus.getDefault().register(this); } @Override @@ -54,6 +77,38 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment { super.onResume(); ((ApplicationPreferencesActivity)getActivity()).getSupportActionBar().setTitle(R.string.preferences__chats); setMediaDownloadSummaries(); + setBackupSummary(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(BackupEvent event) { + ProgressPreference preference = (ProgressPreference)findPreference(TextSecurePreferences.BACKUP_NOW); + + if (event.getType() == BackupEvent.Type.PROGRESS) { + preference.setEnabled(false); + preference.setSummary(getString(R.string.ChatsPreferenceFragment_in_progress)); + preference.setProgress(event.getCount()); + } else if (event.getType() == BackupEvent.Type.FINISHED) { + preference.setEnabled(true); + preference.setProgressVisible(false); + setBackupSummary(); + } + } + + private void setBackupSummary() { + findPreference(TextSecurePreferences.BACKUP_NOW) + .setSummary(String.format(getString(R.string.ChatsPreferenceFragment_last_backup_s), BackupUtil.getLastBackupTime(getContext(), Locale.US))); } private void setMediaDownloadSummaries() { @@ -78,6 +133,46 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment { : TextUtils.join(", ", outValues); } + private class BackupClickListener implements Preference.OnPreferenceClickListener { + @Override + public boolean onPreferenceClick(Preference preference) { + Permissions.with(ChatsPreferenceFragment.this) + .request(Manifest.permission.WRITE_EXTERNAL_STORAGE) + .ifNecessary() + .onAllGranted(() -> { + if (!((SwitchPreferenceCompat)preference).isChecked()) { + BackupDialog.showEnableBackupDialog(getActivity(), (SwitchPreferenceCompat)preference); + } else { + BackupDialog.showDisableBackupDialog(getActivity(), (SwitchPreferenceCompat)preference); + } + }) + .withPermanentDenialDialog(getString(R.string.ChatsPreferenceFragment_signal_requires_external_storage_permission_in_order_to_create_backups)) + .execute(); + + return true; + } + } + + private class BackupCreateListener implements Preference.OnPreferenceClickListener { + @SuppressLint("StaticFieldLeak") + @Override + public boolean onPreferenceClick(Preference preference) { + Permissions.with(ChatsPreferenceFragment.this) + .request(Manifest.permission.WRITE_EXTERNAL_STORAGE) + .ifNecessary() + .onAllGranted(() -> { + Log.w(TAG, "Queing backup..."); + ApplicationContext.getInstance(getContext()) + .getJobManager() + .add(new LocalBackupJob(getContext())); + }) + .withPermanentDenialDialog(getString(R.string.ChatsPreferenceFragment_signal_requires_external_storage_permission_in_order_to_create_backups)) + .execute(); + + return true; + } + } + private class TrimNowClickListener implements Preference.OnPreferenceClickListener { @Override public boolean onPreferenceClick(Preference preference) { diff --git a/src/org/thoughtcrime/securesms/preferences/widgets/ProgressPreference.java b/src/org/thoughtcrime/securesms/preferences/widgets/ProgressPreference.java new file mode 100644 index 000000000..c47a86251 --- /dev/null +++ b/src/org/thoughtcrime/securesms/preferences/widgets/ProgressPreference.java @@ -0,0 +1,61 @@ +package org.thoughtcrime.securesms.preferences.widgets; + + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceViewHolder; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import org.thoughtcrime.securesms.R; + +public class ProgressPreference extends Preference { + + private View container; + private TextView progressText; + + public ProgressPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initialize(); + } + + public ProgressPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(); + } + + public ProgressPreference(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public ProgressPreference(Context context) { + super(context); + initialize(); + } + + private void initialize() { + setWidgetLayoutResource(R.layout.preference_widget_progress); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder view) { + super.onBindViewHolder(view); + + this.container = view.findViewById(R.id.container); + this.progressText = (TextView) view.findViewById(R.id.progress_text); + + this.container.setVisibility(View.GONE); + } + + public void setProgress(int count) { + container.setVisibility(View.VISIBLE); + progressText.setText(getContext().getString(R.string.ProgressPreference_d_messages_so_far, count)); + } + + public void setProgressVisible(boolean visible) { + container.setVisibility(visible ? View.VISIBLE : View.GONE); + } + +} diff --git a/src/org/thoughtcrime/securesms/service/LocalBackupListener.java b/src/org/thoughtcrime/securesms/service/LocalBackupListener.java new file mode 100644 index 000000000..d60dad349 --- /dev/null +++ b/src/org/thoughtcrime/securesms/service/LocalBackupListener.java @@ -0,0 +1,39 @@ +package org.thoughtcrime.securesms.service; + + +import android.content.Context; +import android.content.Intent; + +import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.jobs.LocalBackupJob; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +import java.util.concurrent.TimeUnit; + +public class LocalBackupListener extends PersistentAlarmManagerListener { + + private static final long INTERVAL = TimeUnit.DAYS.toMillis(1); + + @Override + protected long getNextScheduledExecutionTime(Context context) { + return TextSecurePreferences.getNextBackupTime(context); + } + + @Override + protected long onAlarm(Context context, long scheduledTime) { + if (TextSecurePreferences.isBackupEnabled(context)) { + ApplicationContext.getInstance(context).getJobManager().add(new LocalBackupJob(context)); + } + + long nextTime = System.currentTimeMillis() + INTERVAL; + TextSecurePreferences.setNextBackupTime(context, nextTime); + + return nextTime; + } + + public static void schedule(Context context) { + if (TextSecurePreferences.isBackupEnabled(context)) { + new LocalBackupListener().onReceive(context, new Intent()); + } + } +} diff --git a/src/org/thoughtcrime/securesms/util/BackupUtil.java b/src/org/thoughtcrime/securesms/util/BackupUtil.java new file mode 100644 index 000000000..9c39f5f06 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/BackupUtil.java @@ -0,0 +1,160 @@ +package org.thoughtcrime.securesms.util; + + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.Log; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.database.NoExternalStorageException; +import org.whispersystems.libsignal.util.ByteUtil; + +import java.io.File; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Locale; + +public class BackupUtil { + + private static final String TAG = BackupUtil.class.getSimpleName(); + + public static @NonNull String getLastBackupTime(@NonNull Context context, @NonNull Locale locale) { + try { + BackupInfo backup = getLatestBackup(); + + if (backup == null) return context.getString(R.string.BackupUtil_never); + else return DateUtils.getExtendedRelativeTimeSpanString(context, locale, backup.getTimestamp()); + } catch (NoExternalStorageException e) { + Log.w(TAG, e); + return context.getString(R.string.BackupUtil_unknown); + } + } + + public static @Nullable BackupInfo getLatestBackup() throws NoExternalStorageException { + File backupDirectory = StorageUtil.getBackupDirectory(); + File[] backups = backupDirectory.listFiles(); + BackupInfo latestBackup = null; + + for (File backup : backups) { + long backupTimestamp = getBackupTimestamp(backup); + + if (latestBackup == null || (backupTimestamp != -1 && backupTimestamp > latestBackup.getTimestamp())) { + latestBackup = new BackupInfo(backupTimestamp, backup.length(), backup); + } + } + + return latestBackup; + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public static void deleteAllBackups() { + try { + File backupDirectory = StorageUtil.getBackupDirectory(); + File[] backups = backupDirectory.listFiles(); + + for (File backup : backups) { + if (backup.isFile()) backup.delete(); + } + } catch (NoExternalStorageException e) { + Log.w(TAG, e); + } + } + + public static void deleteOldBackups() { + try { + File backupDirectory = StorageUtil.getBackupDirectory(); + File[] backups = backupDirectory.listFiles(); + + if (backups != null && backups.length > 5) { + Arrays.sort(backups, (left, right) -> { + long leftTimestamp = getBackupTimestamp(left); + long rightTimestamp = getBackupTimestamp(right); + + if (leftTimestamp == -1 && rightTimestamp == -1) return 0; + else if (leftTimestamp == -1) return 1; + else if (rightTimestamp == -1) return -1; + + return (int)(rightTimestamp - leftTimestamp); + }); + + for (int i=5;i