diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2016-04-25 11:23:42 +0300 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2016-04-25 11:23:42 +0300 | 
| commit | 32478332830697ef36a6bc6bcc0ef3b914a86e6d (patch) | |
| tree | 2184d8902a3a68d653cd5df6535c5019a34ad4d5 /main/src | |
| parent | 4d8c036c367ad861a3d53a3a8c60074b9ad2d923 (diff) | |
Implement custom marschal/unmarschal for LogItem, hopefully this will fix the problems.
Diffstat (limited to 'main/src')
6 files changed, 437 insertions, 252 deletions
| diff --git a/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java b/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java index dfa6c5fa..7bb9d134 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java +++ b/main/src/main/java/de/blinkt/openvpn/core/LogFileHandler.java @@ -8,7 +8,6 @@ package de.blinkt.openvpn.core;  import android.os.Handler;  import android.os.Looper;  import android.os.Message; -import android.os.Parcel;  import java.io.BufferedInputStream;  import java.io.File; @@ -18,6 +17,7 @@ import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream; +import java.io.UnsupportedEncodingException;  import java.nio.ByteBuffer;  import java.util.Locale; @@ -50,14 +50,14 @@ class LogFileHandler extends Handler {                      throw new RuntimeException("mLogFile not null");                  readLogCache((File) msg.obj);                  openLogFile((File) msg.obj); -            } else if (msg.what == LOG_MESSAGE && msg.obj instanceof VpnStatus.LogItem) { +            } else if (msg.what == LOG_MESSAGE && msg.obj instanceof LogItem) {                  // Ignore log messages if not yet initialized                  if (mLogFile == null)                      return; -                writeLogItemToDisk((VpnStatus.LogItem) msg.obj); +                writeLogItemToDisk((LogItem) msg.obj);              } else if (msg.what == TRIM_LOG_FILE) {                  trimLogFile(); -                for (VpnStatus.LogItem li : VpnStatus.getlogbuffer()) +                for (LogItem li : VpnStatus.getlogbuffer())                      writeLogItemToDisk(li);              } else if (msg.what == FLUSH_TO_DISK) {                  flushToDisk(); @@ -84,15 +84,13 @@ class LogFileHandler extends Handler {          }      } -    private void writeLogItemToDisk(VpnStatus.LogItem li) throws IOException { -        Parcel p = Parcel.obtain(); -        li.writeToParcel(p, 0); +    private void writeLogItemToDisk(LogItem li) throws IOException { +          // We do not really care if the log cache breaks between Android upgrades,          // write binary format to disc -        byte[] liBytes = p.marshall(); +        byte[] liBytes = li.getMarschaledBytes();          writeEscapedBytes(liBytes); -        p.recycle();      }      public void writeEscapedBytes(byte[] bytes) throws IOException { @@ -211,11 +209,9 @@ class LogFileHandler extends Handler {      } -    protected void restoreLogItem(byte[] buf, int len) { -        Parcel p = Parcel.obtain(); -        p.unmarshall(buf, 0, len); -        p.setDataPosition(0); -        VpnStatus.LogItem li = VpnStatus.LogItem.CREATOR.createFromParcel(p); +    protected void restoreLogItem(byte[] buf, int len) throws UnsupportedEncodingException { + +        LogItem li = new LogItem(buf, len);          if (li.verify()) {              VpnStatus.newLogItem(li, true);          } else { @@ -223,7 +219,6 @@ class LogFileHandler extends Handler {                      "Could not read log item from file: %d: %s",                       len, bytesToHex(buf, Math.max(len, 80))));          } -        p.recycle();      }      final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); diff --git a/main/src/main/java/de/blinkt/openvpn/core/LogItem.java b/main/src/main/java/de/blinkt/openvpn/core/LogItem.java new file mode 100644 index 00000000..57bc3e1e --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/core/LogItem.java @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2012-2016 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.core; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.Log; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.FormatFlagsConversionMismatchException; +import java.util.Locale; +import java.util.UnknownFormatConversionException; + +import de.blinkt.openvpn.R; + +/** + * Created by arne on 24.04.16. + */ +public class LogItem implements Parcelable { +    private Object[] mArgs = null; +    private String mMessage = null; +    private int mRessourceId; +    // Default log priority +    VpnStatus.LogLevel mLevel = VpnStatus.LogLevel.INFO; +    private long logtime = System.currentTimeMillis(); +    private int mVerbosityLevel = -1; + +    private LogItem(int ressourceId, Object[] args) { +        mRessourceId = ressourceId; +        mArgs = args; +    } + +    public LogItem(VpnStatus.LogLevel level, int verblevel, String message) { +        mMessage = message; +        mLevel = level; +        mVerbosityLevel = verblevel; +    } + +    @Override +    public int describeContents() { +        return 0; +    } + + +    @Override +    public void writeToParcel(Parcel dest, int flags) { +        dest.writeArray(mArgs); +        dest.writeString(mMessage); +        dest.writeInt(mRessourceId); +        dest.writeInt(mLevel.getInt()); +        dest.writeInt(mVerbosityLevel); + +        dest.writeLong(logtime); +    } + +    @Override +    public boolean equals(Object obj) { +        if (!(obj instanceof LogItem)) +            return obj.equals(this); +        LogItem other = (LogItem) obj; + +        return Arrays.equals(mArgs, other.mArgs) && +                ((other.mMessage == null && mMessage == other.mMessage) || +                        mMessage.equals(other.mMessage)) && +                mRessourceId == other.mRessourceId && +                ((mLevel == null && other.mLevel == mLevel) || +                        other.mLevel.equals(mLevel)) && +                mVerbosityLevel == other.mVerbosityLevel && +                logtime == other.logtime; + + +    } + +    public byte[] getMarschaledBytes() throws UnsupportedEncodingException { +        ByteBuffer bb = ByteBuffer.allocate(16384); + + +        bb.put((byte) 0x0);               //version +        bb.putLong(logtime);              //8 +        bb.putInt(mVerbosityLevel);      //4 +        bb.putInt(mLevel.getInt()); +        bb.putInt(mRessourceId); +        if (mMessage == null || mMessage.length() == 0) { +            bb.putInt(0); +        } else { +            marschalString(mMessage, bb); +        } +        if (mArgs == null || mArgs.length == 0) { +            bb.putInt(0); +        } else { +            bb.putInt(mArgs.length); +            for (Object o : mArgs) { +                if (o instanceof String) { +                    bb.putChar('s'); +                    marschalString((String) o, bb); +                } else if (o instanceof Integer) { +                    bb.putChar('i'); +                    bb.putInt((Integer) o); +                } else if (o instanceof Float) { +                    bb.putChar('f'); +                    bb.putFloat((Float) o); +                } else if (o instanceof Double) { +                    bb.putChar('d'); +                    bb.putDouble((Double) o); +                } else if (o instanceof Long) { +                    bb.putChar('l'); +                    bb.putLong((Long) o); +                } else if (o == null) { +                    bb.putChar('0'); +                } else { +                    VpnStatus.logDebug("Unknown object for LogItem marschaling " + o); +                    bb.putChar('s'); +                    marschalString(o.toString(), bb); +                } + +            } +        } + +        int pos = bb.position(); +        bb.rewind(); +        return Arrays.copyOf(bb.array(), pos); + +    } + +    public LogItem(byte[] in, int length) throws UnsupportedEncodingException { +        ByteBuffer bb = ByteBuffer.wrap(in, 0, length); +        bb.get(); // ignore version +        logtime = bb.getLong(); +        mVerbosityLevel = bb.getInt(); +        mLevel = VpnStatus.LogLevel.getEnumByValue(bb.getInt()); +        mRessourceId = bb.getInt(); +        int len = bb.getInt(); +        if (len == 0) { +            mMessage = null; +        } else { +            byte[] utf8bytes = new byte[len]; +            bb.get(utf8bytes); +            mMessage = new String(utf8bytes, "UTF-8"); +        } +        int numArgs = bb.getInt(); +        if (numArgs > 30) { +            throw new IndexOutOfBoundsException("Too many arguments for Logitem to unmarschal"); +        } +        if (numArgs == 0) { +            mArgs = null; +        } else { +            mArgs = new Object[numArgs]; +            for (int i = 0; i < numArgs; i++) { +                char type = bb.getChar(); +                switch (type) { +                    case 's': +                        mArgs[i] = unmarschalString(bb); +                        break; +                    case 'i': +                        mArgs[i] = bb.getInt(); +                        break; +                    case 'd': +                        mArgs[i] = bb.getDouble(); +                        break; +                    case 'f': +                        mArgs[i] = bb.getFloat(); +                        break; +                    case 'l': +                        mArgs[i] = bb.getLong(); +                        break; +                    case '0': +                        mArgs[i] = null; +                        break; +                    default: +                        throw new UnsupportedEncodingException("Unknown format type: " + type); +                } +            } +        } +        if (bb.hasRemaining()) +            throw new UnsupportedEncodingException(bb.remaining() + " bytes left after unmarshaling everything"); +    } + +    private void marschalString(String str, ByteBuffer bb) throws UnsupportedEncodingException { +        byte[] utf8bytes = str.getBytes("UTF-8"); +        bb.putInt(utf8bytes.length); +        bb.put(utf8bytes); +    } + +    private String unmarschalString(ByteBuffer bb) throws UnsupportedEncodingException { +        int len = bb.getInt(); +        byte[] utf8bytes = new byte[len]; +        bb.get(utf8bytes); +        return new String(utf8bytes, "UTF-8"); +    } + + +    public LogItem(Parcel in) { +        mArgs = in.readArray(Object.class.getClassLoader()); +        mMessage = in.readString(); +        mRessourceId = in.readInt(); +        mLevel = VpnStatus.LogLevel.getEnumByValue(in.readInt()); +        mVerbosityLevel = in.readInt(); +        logtime = in.readLong(); +    } + +    public static final Creator<LogItem> CREATOR +            = new Creator<LogItem>() { +        public LogItem createFromParcel(Parcel in) { +            return new LogItem(in); +        } + +        public LogItem[] newArray(int size) { +            return new LogItem[size]; +        } +    }; + +    public LogItem(VpnStatus.LogLevel loglevel, int ressourceId, Object... args) { +        mRessourceId = ressourceId; +        mArgs = args; +        mLevel = loglevel; +    } + + +    public LogItem(VpnStatus.LogLevel loglevel, String msg) { +        mLevel = loglevel; +        mMessage = msg; +    } + + +    public LogItem(VpnStatus.LogLevel loglevel, int ressourceId) { +        mRessourceId = ressourceId; +        mLevel = loglevel; +    } + +    public String getString(Context c) { +        try { +            if (mMessage != null) { +                return mMessage; +            } else { +                if (c != null) { +                    if (mRessourceId == R.string.mobile_info) +                        return getMobileInfoString(c); +                    if (mArgs == null) +                        return c.getString(mRessourceId); +                    else +                        return c.getString(mRessourceId, mArgs); +                } else { +                    String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId); +                    if (mArgs != null) +                        str += join("|", mArgs); + +                    return str; +                } +            } +        } catch (UnknownFormatConversionException e) { +            if (c != null) +                throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); +            else +                throw e; +        } catch (java.util.FormatFlagsConversionMismatchException e) { +            if (c != null) +                throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion()); +            else +                throw e; +        } + +    } + + +    // TextUtils.join will cause not macked exeception in tests .... +    public static String join(CharSequence delimiter, Object[] tokens) { +        StringBuilder sb = new StringBuilder(); +        boolean firstTime = true; +        for (Object token : tokens) { +            if (firstTime) { +                firstTime = false; +            } else { +                sb.append(delimiter); +            } +            sb.append(token); +        } +        return sb.toString(); +    } + + +    public VpnStatus.LogLevel getLogLevel() { +        return mLevel; +    } + + +    @Override +    public String toString() { +        return getString(null); +    } + +    // The lint is wrong here +    @SuppressLint("StringFormatMatches") +    private String getMobileInfoString(Context c) { +        c.getPackageManager(); +        String apksign = "error getting package signature"; + +        String version = "error getting version"; +        try { +            @SuppressLint("PackageManagerGetSignatures") +            Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; +            CertificateFactory cf = CertificateFactory.getInstance("X.509"); +            X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); +            MessageDigest md = MessageDigest.getInstance("SHA-1"); +            byte[] der = cert.getEncoded(); +            md.update(der); +            byte[] digest = md.digest(); + +            if (Arrays.equals(digest, VpnStatus.officalkey)) +                apksign = c.getString(R.string.official_build); +            else if (Arrays.equals(digest, VpnStatus.officaldebugkey)) +                apksign = c.getString(R.string.debug_build); +            else if (Arrays.equals(digest, VpnStatus.amazonkey)) +                apksign = "amazon version"; +            else if (Arrays.equals(digest, VpnStatus.fdroidkey)) +                apksign = "F-Droid built and signed version"; +            else +                apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName()); + +            PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); +            version = packageinfo.versionName; + +        } catch (PackageManager.NameNotFoundException | CertificateException | +                NoSuchAlgorithmException ignored) { +        } + +        Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); +        argsext[argsext.length - 1] = apksign; +        argsext[argsext.length - 2] = version; + +        return c.getString(R.string.mobile_info, argsext); + +    } + +    public long getLogtime() { +        return logtime; +    } + + +    public int getVerbosityLevel() { +        if (mVerbosityLevel == -1) { +            // Hack: +            // For message not from OpenVPN, report the status level as log level +            return mLevel.getInt(); +        } +        return mVerbosityLevel; +    } + +    public boolean verify() { +        if (mLevel == null) +            return false; + +        if (mMessage == null && mRessourceId == 0) +            return false; + +        return true; +    } +} diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index 7fd43906..4f743a19 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -25,9 +25,7 @@ import java.util.regex.Matcher;  import java.util.regex.Pattern;
  import de.blinkt.openvpn.R;
 -import de.blinkt.openvpn.VpnProfile;
  import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus;
 -import de.blinkt.openvpn.core.VpnStatus.LogItem;
  public class OpenVPNThread implements Runnable {
      private static final String DUMP_PATH_STRING = "Dump path: ";
 @@ -69,7 +67,7 @@ public class OpenVPNThread implements Runnable {          try {
              Log.i(TAG, "Starting openvpn");
              startOpenVPNThreadArgs(mArgv, mProcessEnv);
 -            Log.i(TAG, "OpenVPN process exited"); +            Log.i(TAG, "OpenVPN process exited");
          } catch (Exception e) {
              VpnStatus.logException("Starting OpenVPN Thread", e);
              Log.e(TAG, "OpenVPNThread Got " + e.toString());
 diff --git a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java index 92ab5900..d23f0013 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/main/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -5,39 +5,18 @@  package de.blinkt.openvpn.core; -import android.annotation.SuppressLint;  import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.Signature;  import android.os.Build;  import android.os.HandlerThread;  import android.os.Message; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Log; -import java.io.ByteArrayInputStream; -import java.io.DataOutputStream;  import java.io.File; -import java.io.OutputStream;  import java.io.PrintWriter;  import java.io.StringWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.FormatFlagsConversionMismatchException;  import java.util.LinkedList;  import java.util.Locale; -import java.util.UnknownFormatConversionException;  import java.util.Vector; -import de.blinkt.openvpn.BuildConfig;  import de.blinkt.openvpn.R;  public class VpnStatus { @@ -206,205 +185,6 @@ public class VpnStatus {      } -    public static class LogItem implements Parcelable { -        private Object[] mArgs = null; -        private String mMessage = null; -        private int mRessourceId; -        // Default log priority -        LogLevel mLevel = LogLevel.INFO; -        private long logtime = System.currentTimeMillis(); -        private int mVerbosityLevel = -1; - -        private LogItem(int ressourceId, Object[] args) { -            mRessourceId = ressourceId; -            mArgs = args; -        } - -        public LogItem(LogLevel level, int verblevel, String message) { -            mMessage = message; -            mLevel = level; -            mVerbosityLevel = verblevel; -        } - -        @Override -        public int describeContents() { -            return 0; -        } - - -        @Override -        public void writeToParcel(Parcel dest, int flags) { -            dest.writeArray(mArgs); -            dest.writeString(mMessage); -            dest.writeInt(mRessourceId); -            dest.writeInt(mLevel.getInt()); -            dest.writeInt(mVerbosityLevel); - -            dest.writeLong(logtime); -        } - -        public LogItem(Parcel in) { -            mArgs = in.readArray(Object.class.getClassLoader()); -            mMessage = in.readString(); -            mRessourceId = in.readInt(); -            mLevel = LogLevel.getEnumByValue(in.readInt()); -            mVerbosityLevel = in.readInt(); -            logtime = in.readLong(); -        } - -        public static final Parcelable.Creator<LogItem> CREATOR -                = new Parcelable.Creator<LogItem>() { -            public LogItem createFromParcel(Parcel in) { -                return new LogItem(in); -            } - -            public LogItem[] newArray(int size) { -                return new LogItem[size]; -            } -        }; - -        public LogItem(LogLevel loglevel, int ressourceId, Object... args) { -            mRessourceId = ressourceId; -            mArgs = args; -            mLevel = loglevel; -        } - - -        public LogItem(LogLevel loglevel, String msg) { -            mLevel = loglevel; -            mMessage = msg; -        } - - -        public LogItem(LogLevel loglevel, int ressourceId) { -            mRessourceId = ressourceId; -            mLevel = loglevel; -        } - -        public String getString(Context c) { -            try { -                if (mMessage != null) { -                    return mMessage; -                } else { -                    if (c != null) { -                        if (mRessourceId == R.string.mobile_info) -                            return getMobileInfoString(c); -                        if (mArgs == null) -                            return c.getString(mRessourceId); -                        else -                            return c.getString(mRessourceId, mArgs); -                    } else { -                        String str = String.format(Locale.ENGLISH, "Log (no context) resid %d", mRessourceId); -                        if (mArgs != null) -                            str += join("|", mArgs); - -                        return str; -                    } -                } -            } catch (UnknownFormatConversionException e) { -                if (c != null) -                    throw new UnknownFormatConversionException(e.getLocalizedMessage() + getString(null)); -                else -                    throw e; -            } catch (java.util.FormatFlagsConversionMismatchException e) { -                if (c != null) -                    throw new FormatFlagsConversionMismatchException(e.getLocalizedMessage() + getString(null), e.getConversion()); -                else -                    throw e; -            } - -        } - - -        // TextUtils.join will cause not macked exeception in tests .... -        public static String join(CharSequence delimiter, Object[] tokens) { -            StringBuilder sb = new StringBuilder(); -            boolean firstTime = true; -            for (Object token: tokens) { -                if (firstTime) { -                    firstTime = false; -                } else { -                    sb.append(delimiter); -                } -                sb.append(token); -            } -            return sb.toString(); -        } - - - -        public LogLevel getLogLevel() { -            return mLevel; -        } - -        // The lint is wrong here -        @SuppressLint("StringFormatMatches") -        private String getMobileInfoString(Context c) { -            c.getPackageManager(); -            String apksign = "error getting package signature"; - -            String version = "error getting version"; -            try { -                @SuppressLint("PackageManagerGetSignatures") -                Signature raw = c.getPackageManager().getPackageInfo(c.getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; -                CertificateFactory cf = CertificateFactory.getInstance("X.509"); -                X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); -                MessageDigest md = MessageDigest.getInstance("SHA-1"); -                byte[] der = cert.getEncoded(); -                md.update(der); -                byte[] digest = md.digest(); - -                if (Arrays.equals(digest, officalkey)) -                    apksign = c.getString(R.string.official_build); -                else if (Arrays.equals(digest, officaldebugkey)) -                    apksign = c.getString(R.string.debug_build); -                else if (Arrays.equals(digest, amazonkey)) -                    apksign = "amazon version"; -                else if (Arrays.equals(digest, fdroidkey)) -                    apksign = "F-Droid built and signed version"; -                else -                    apksign = c.getString(R.string.built_by, cert.getSubjectX500Principal().getName()); - -                PackageInfo packageinfo = c.getPackageManager().getPackageInfo(c.getPackageName(), 0); -                version = packageinfo.versionName; - -            } catch (NameNotFoundException | CertificateException | -                    NoSuchAlgorithmException ignored) { -            } - -            Object[] argsext = Arrays.copyOf(mArgs, mArgs.length); -            argsext[argsext.length - 1] = apksign; -            argsext[argsext.length - 2] = version; - -            return c.getString(R.string.mobile_info, argsext); - -        } - -        public long getLogtime() { -            return logtime; -        } - - -        public int getVerbosityLevel() { -            if (mVerbosityLevel == -1) { -                // Hack: -                // For message not from OpenVPN, report the status level as log level -                return mLevel.getInt(); -            } -            return mVerbosityLevel; -        } - -        public boolean verify() { -            if (mLevel == null) -                return false; - -            if (mMessage == null && mRessourceId == 0) -                return false; - -            return true; -        } -    } -      public interface LogListener {          void newLog(LogItem logItem);      } @@ -425,7 +205,7 @@ public class VpnStatus {      public synchronized static void clearLog() {          logbuffer.clear();          logInformation(); -        if (mLogFileHandler!=null) +        if (mLogFileHandler != null)              mLogFileHandler.sendEmptyMessage(LogFileHandler.TRIM_LOG_FILE);      } @@ -438,7 +218,7 @@ public class VpnStatus {          }          logInfo(R.string.mobile_info, Build.MODEL, Build.BOARD, Build.BRAND, Build.VERSION.SDK_INT, -                nativeAPI , Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", ""); +                nativeAPI, Build.VERSION.RELEASE, Build.ID, Build.FINGERPRINT, "", "");      }      public synchronized static void addLogListener(LogListener ll) { @@ -607,7 +387,7 @@ public class VpnStatus {              logbuffer.addFirst(logItem);          } else {              logbuffer.addLast(logItem); -            if (mLogFileHandler!=null) { +            if (mLogFileHandler != null) {                  Message m = mLogFileHandler.obtainMessage(LogFileHandler.LOG_MESSAGE, logItem);                  mLogFileHandler.sendMessage(m);              } @@ -616,7 +396,7 @@ public class VpnStatus {          if (logbuffer.size() > MAXLOGENTRIES + MAXLOGENTRIES / 2) {              while (logbuffer.size() > MAXLOGENTRIES)                  logbuffer.removeFirst(); -            if (mLogFileHandler!=null) +            if (mLogFileHandler != null)                  mLogFileHandler.sendMessage(mLogFileHandler.obtainMessage(LogFileHandler.TRIM_LOG_FILE));          } diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java index a620beb4..d3381bcb 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -22,7 +22,6 @@ import android.os.Bundle;  import android.os.Handler;  import android.os.Handler.Callback;  import android.os.Message; -import android.preference.Preference;  import android.preference.PreferenceManager;  import android.support.annotation.Nullable;  import android.text.SpannableString; @@ -63,7 +62,7 @@ import de.blinkt.openvpn.core.OpenVPNService;  import de.blinkt.openvpn.core.ProfileManager;  import de.blinkt.openvpn.core.VpnStatus;  import de.blinkt.openvpn.core.VpnStatus.ConnectionStatus; -import de.blinkt.openvpn.core.VpnStatus.LogItem; +import de.blinkt.openvpn.core.LogItem;  import de.blinkt.openvpn.core.VpnStatus.LogListener;  import de.blinkt.openvpn.core.VpnStatus.StateListener; diff --git a/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java b/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java index f86dbcdc..c35df598 100644 --- a/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java +++ b/main/src/test/java/de/blinkt/openvpn/core/TestLogFileHandler.java @@ -1,9 +1,6 @@  package de.blinkt.openvpn.core;  import android.annotation.SuppressLint; -import android.os.Looper; -import android.os.Message; -import android.util.Log;  import junit.framework.Assert; @@ -15,19 +12,18 @@ import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.OutputStream; -import java.io.StringBufferInputStream; +import java.io.UnsupportedEncodingException;  import java.util.Arrays;  public class TestLogFileHandler { -    byte[] testUnescaped = new byte[] {0x00, 0x55, -27, 0x00, 0x56, 0x10, -128, 0x55, 0x54}; -    byte[] expectedEscaped = new byte[] {0x55, 0x00, 0x00, 0x00, 0x09, 0x00, 0x56, 0x00, -27, 0x00, 0x56, 0x01, 0x10, -128, 0x56, 0x00, 0x54}; +    byte[] testUnescaped = new byte[]{0x00, 0x55, -27, 0x00, 0x56, 0x10, -128, 0x55, 0x54}; +    byte[] expectedEscaped = new byte[]{0x55, 0x00, 0x00, 0x00, 0x09, 0x00, 0x56, 0x00, -27, 0x00, 0x56, 0x01, 0x10, -128, 0x56, 0x00, 0x54};      private TestingLogFileHandler lfh;      @Before -    public void setup() -    { +    public void setup() {          lfh = new TestingLogFileHandler();      } @@ -55,6 +51,46 @@ public class TestLogFileHandler {      } +    @Test +    public void testMarschal() throws UnsupportedEncodingException { +        LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, 72, "foobar"); +        LogItem li2 = marschalAndBack(li); +        testEquals(li, li2); +        Assert.assertEquals(li, li2); +    } + +    @Test +    public void testMarschalArgs() throws UnsupportedEncodingException { +        LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, 72, 772, "sinnloser Text", 7723, 723.2f, 7.2); +        LogItem li2 = marschalAndBack(li); +        testEquals(li, li2); +        Assert.assertEquals(li, li2); +    } + +    @Test +    public void testMarschalString() throws UnsupportedEncodingException { +        LogItem li = new LogItem(VpnStatus.LogLevel.DEBUG, "Nutzlose Nachricht"); +        LogItem li2 = marschalAndBack(li); +        testEquals(li, li2); +        Assert.assertEquals(li, li2); +    } + + +    private void testEquals(LogItem li, LogItem li2) { +        Assert.assertEquals(li.getLogLevel(), li2.getLogLevel()); +        Assert.assertEquals(li.getLogtime(), li2.getLogtime()); +        Assert.assertEquals(li.getVerbosityLevel(), li2.getVerbosityLevel()); +        Assert.assertEquals(li.toString(), li2.toString()); + +    } + +    private LogItem marschalAndBack(LogItem li) throws UnsupportedEncodingException { +        byte[] bytes = li.getMarschaledBytes(); + +        return new LogItem(bytes, bytes.length); +    } + +      @SuppressLint("HandlerLeak")      static class TestingLogFileHandler extends LogFileHandler { @@ -78,4 +114,6 @@ public class TestLogFileHandler {              mRestoredByteArray = Arrays.copyOf(buf, len);          }      } + +  }
\ No newline at end of file | 
