aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java')
-rw-r--r--src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java278
1 files changed, 278 insertions, 0 deletions
diff --git a/src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java b/src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java
new file mode 100644
index 00000000..39e623bb
--- /dev/null
+++ b/src/com/cyanogenmod/filemanager/commands/secure/ChecksumCommand.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.filemanager.commands.secure;
+
+import android.util.Log;
+
+import com.android.internal.util.HexDump;
+import com.cyanogenmod.filemanager.commands.AsyncResultListener;
+import com.cyanogenmod.filemanager.commands.ChecksumExecutable;
+import com.cyanogenmod.filemanager.console.ExecutionException;
+import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
+import com.cyanogenmod.filemanager.console.secure.SecureConsole;
+
+import de.schlichtherle.truezip.file.TFile;
+import de.schlichtherle.truezip.file.TFileInputStream;
+
+import java.io.File;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.util.Locale;
+
+/**
+ * A class for calculate MD5 and SHA-1 checksums of a file system object.<br />
+ * <br />
+ * Partial results are returned in order (MD5 -> SHA1)
+ */
+public class ChecksumCommand extends Program implements ChecksumExecutable {
+
+ private static final String TAG = "ChecksumCommand"; //$NON-NLS-1$
+
+ private final File mSrc;
+ private final String[] mChecksums;
+ private final AsyncResultListener mAsyncResultListener;
+
+ private boolean mCancelled;
+ private final Object mSync = new Object();
+
+ /**
+ * Constructor of <code>ChecksumCommand</code>.
+ *
+ * @param console The current console
+ * @param src The source file
+ * @param asyncResultListener The partial result listener
+ */
+ public ChecksumCommand(SecureConsole console, String src,
+ AsyncResultListener asyncResultListener) {
+ super(console);
+ this.mAsyncResultListener = asyncResultListener;
+ this.mChecksums = new String[]{null, null};
+ this.mSrc = new File(src);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAsynchronous() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() throws NoSuchFileOrDirectory, ExecutionException {
+
+ if (isTrace()) {
+ Log.v(TAG,
+ String.format("Calculating checksums of file %s", this.mSrc)); //$NON-NLS-1$
+ }
+
+ // Check that the file exists
+ TFile f = getConsole().buildRealFile(this.mSrc.getAbsolutePath());
+ if (!f.exists()) {
+ if (isTrace()) {
+ Log.v(TAG, "Result: FAIL. NoSuchFileOrDirectory"); //$NON-NLS-1$
+ }
+ throw new NoSuchFileOrDirectory(this.mSrc.getAbsolutePath());
+ }
+
+ CHECKSUMS checksum = CHECKSUMS.MD5;
+ try {
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onAsyncStart();
+ }
+
+ // Calculate digests
+ calculateDigest(checksum, f);
+ checksum = CHECKSUMS.SHA1;
+ calculateDigest(checksum, f);
+
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onAsyncEnd(false);
+ }
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onAsyncExitCode(0);
+ }
+
+ if (isTrace()) {
+ Log.v(TAG, "Result: OK"); //$NON-NLS-1$
+ }
+
+ } catch (InterruptedException ie) {
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onAsyncEnd(true);
+ }
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onAsyncExitCode(143);
+ }
+
+ if (isTrace()) {
+ Log.v(TAG, "Result: CANCELLED"); //$NON-NLS-1$
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG,
+ String.format(
+ "Fail to calculate %s checksum of file %s", //$NON-NLS-1$
+ checksum.name(),
+ this.mSrc.getAbsolutePath()),
+ e);
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onException(e);
+ }
+ if (isTrace()) {
+ Log.v(TAG, "Result: FAIL"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCancelled() {
+ synchronized (this.mSync) {
+ return this.mCancelled;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean cancel() {
+ try {
+ synchronized (this.mSync) {
+ this.mCancelled = true;
+ }
+ } catch (Throwable _throw) {/**NON BLOCK**/}
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean end() {
+ return cancel();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setOnEndListener(OnEndListener onEndListener) {
+ //Ignore. Java console don't use this
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setOnCancelListener(OnCancelListener onCancelListener) {
+ //Ignore. Java console don't use this
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String[] getResult() {
+ return this.mChecksums;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getChecksum(CHECKSUMS checksum) {
+ return getResult()[checksum.ordinal()];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCancellable() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AsyncResultListener getAsyncResultListener() {
+ return this.mAsyncResultListener;
+ }
+
+ /**
+ * Method that calculate a digest of the file for the source file
+ *
+ * @param type The type of digest to obtain
+ * @pa
+ * @throws InterruptedException If the operation was cancelled
+ * @throws Exception If an error occurs
+ */
+ private void calculateDigest(CHECKSUMS type, TFile file)
+ throws InterruptedException, Exception {
+
+ InputStream is = null;
+ try {
+ MessageDigest md = MessageDigest.getInstance(type.name());
+ is = new TFileInputStream(file);
+
+ // Start digesting
+ byte[] data = new byte[getBufferSize()];
+ int read = 0;
+ while ((read = is.read(data, 0, getBufferSize())) != -1) {
+ checkCancelled();
+ md.update(data, 0, read);
+ }
+ checkCancelled();
+
+ // Finally digest
+ this.mChecksums[type.ordinal()] =
+ HexDump.toHexString(md.digest()).toLowerCase(Locale.ROOT);
+ checkCancelled();
+ if (this.mAsyncResultListener != null) {
+ this.mAsyncResultListener.onPartialResult(this.mChecksums[type.ordinal()]);
+ }
+
+ } finally {
+ try {
+ if (is != null) {
+ is.close();
+ }
+ } catch (Exception e) {/**NON BLOCK**/}
+ }
+ }
+
+ /**
+ * Checks if the operation was cancelled
+ *
+ * @throws InterruptedException If the operation was cancelled
+ */
+ private void checkCancelled() throws InterruptedException {
+ synchronized (this.mSync) {
+ if (this.mCancelled) {
+ throw new InterruptedException();
+ }
+ }
+ }
+}