org.strongswan.android.data.VpnProfileDataSource.java Source code

Java tutorial

Introduction

Here is the source code for org.strongswan.android.data.VpnProfileDataSource.java

Source

/*
 * Copyright (C) 2012-2016 Tobias Brunner
 * Copyright (C) 2012 Giuliano Grassi
 * Copyright (C) 2012 Ralf Sager
 * HSR Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

package org.strongswan.android.data;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class VpnProfileDataSource {
    private static final String TAG = VpnProfileDataSource.class.getSimpleName();
    public static final String KEY_ID = "_id";
    public static final String KEY_NAME = "name";
    public static final String KEY_GATEWAY = "gateway";
    public static final String KEY_VPN_TYPE = "vpn_type";
    public static final String KEY_USERNAME = "username";
    public static final String KEY_PASSWORD = "password";
    public static final String KEY_CERTIFICATE = "certificate";
    public static final String KEY_USER_CERTIFICATE = "user_certificate";
    public static final String KEY_MTU = "mtu";
    public static final String KEY_PORT = "port";
    public static final String KEY_SPLIT_TUNNELING = "split_tunneling";
    public static final String KEY_LOCAL_ID = "local_id";
    public static final String KEY_REMOTE_ID = "remote_id";

    //fancyfon
    public static final String KEY_CERTIFICATE_ID = "id_certificate";
    public static final String KEY_ALLOWED_APPLICATIONS = "allowed_applications";

    private static final String EMPTY_STRING = "";
    private static final String SPLIT_TUNNELING_DEFAULT_VALUE = "0";

    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDatabase;
    private final Context mContext;

    private static final String DATABASE_NAME = "strongswan.db";
    private static final String TABLE_VPNPROFILE = "vpnprofile";
    public static final String KEY_LOGGING_LEVEL = "logging_level";

    private static final int DATABASE_VERSION = 10;

    public static final String DATABASE_CREATE = "CREATE TABLE " + TABLE_VPNPROFILE + " (" + KEY_ID
            + " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_NAME + " TEXT NOT NULL," + KEY_GATEWAY + " TEXT NOT NULL,"
            + KEY_VPN_TYPE + " TEXT NOT NULL," + KEY_USERNAME + " TEXT," + KEY_PASSWORD + " TEXT," + KEY_CERTIFICATE
            + " TEXT," + KEY_USER_CERTIFICATE + " TEXT," + KEY_MTU + " INTEGER," + KEY_PORT + " INTEGER,"
            + KEY_SPLIT_TUNNELING + " INTEGER," + KEY_LOCAL_ID + " TEXT," + KEY_REMOTE_ID + " TEXT," +

            //fancyfon
            KEY_CERTIFICATE_ID + " TEXT," + KEY_ALLOWED_APPLICATIONS + " TEXT," + KEY_LOGGING_LEVEL + " INTEGER"
            + ");";

    private static final String[] ALL_COLUMNS = new String[] { KEY_ID, KEY_NAME, KEY_GATEWAY, KEY_VPN_TYPE,
            KEY_USERNAME, KEY_PASSWORD, KEY_CERTIFICATE, KEY_USER_CERTIFICATE, KEY_MTU, KEY_PORT,
            KEY_SPLIT_TUNNELING, KEY_LOCAL_ID, KEY_REMOTE_ID,

            //fancyfon
            KEY_CERTIFICATE_ID, KEY_ALLOWED_APPLICATIONS, KEY_LOGGING_LEVEL };

    private static class DatabaseHelper extends SQLiteOpenHelper {
        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase database) {
            database.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
            if (oldVersion < 2) {
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_USER_CERTIFICATE + " TEXT;");
            }
            if (oldVersion < 3) {
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_VPN_TYPE + " TEXT DEFAULT '';");
            }
            if (oldVersion < 4) { /* remove NOT NULL constraint from username column */
                updateColumns(db);
            }
            if (oldVersion < 5) {
                fancyfonDatabaseUpdateVersion5(db);
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_MTU + " INTEGER;");
            }
            if (oldVersion < 6) {
                fancyfonDatabaseUpdateVersion6(db);
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_PORT + " INTEGER;");
            }
            if (oldVersion < 7) {
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_SPLIT_TUNNELING + " INTEGER;");
            }
            if (oldVersion < 8) {
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_LOCAL_ID + " TEXT;");
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_REMOTE_ID + " TEXT;");
            }
            if (oldVersion < 10) {
                fancyfonDatabaseUpdateVersion10(db);
            }

        }

        private void fancyfonDatabaseUpdateVersion5(SQLiteDatabase db) {
            db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_ALLOWED_APPLICATIONS + " TEXT;");
        }

        private void fancyfonDatabaseUpdateVersion6(SQLiteDatabase db) {
            db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_CERTIFICATE_ID + " TEXT;");
        }

        private void fancyfonDatabaseUpdateVersion10(SQLiteDatabase db) {
            db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " ADD " + KEY_LOGGING_LEVEL + " INTEGER DEFAULT 1;");
        }

        private void updateColumns(SQLiteDatabase db) {
            db.beginTransaction();
            try {
                db.execSQL("ALTER TABLE " + TABLE_VPNPROFILE + " RENAME TO tmp_" + TABLE_VPNPROFILE + ";");
                db.execSQL(DATABASE_CREATE);
                StringBuilder insert = new StringBuilder("INSERT INTO " + TABLE_VPNPROFILE + " SELECT ");
                SQLiteQueryBuilder.appendColumns(insert, ALL_COLUMNS);
                db.execSQL(insert.append(" FROM tmp_" + TABLE_VPNPROFILE + ";").toString());
                db.execSQL("DROP TABLE tmp_" + TABLE_VPNPROFILE + ";");
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        }
    }

    /**
     * Construct a new VPN profile data source. The context is used to
     * open/create the database.
     * @param context context used to access the database
     */
    public VpnProfileDataSource(Context context) {
        this.mContext = context;
    }

    /**
     * Open the VPN profile data source. The database is automatically created
     * if it does not yet exist. If that fails an exception is thrown.
     * @return itself (allows to chain initialization calls)
     * @throws SQLException if the database could not be opened or created
     */
    public VpnProfileDataSource open() throws SQLException {
        if (mDbHelper == null) {
            mDbHelper = new DatabaseHelper(mContext);
            mDatabase = mDbHelper.getWritableDatabase();
        }
        return this;
    }

    /**
     * Close the data source.
     */
    public void close() {
        if (mDbHelper != null) {
            mDbHelper.close();
            mDbHelper = null;
        }
    }

    /**
     * Insert the given VPN profile into the database.  On success the Id of
     * the object is updated and the object returned.
     *
     * @param profile the profile to add
     * @return the added VPN profile or null, if failed
     */
    public VpnProfile insertProfile(VpnProfile profile) {
        ContentValues values = ContentValuesFromVpnProfile(profile);
        long insertId = mDatabase.insert(TABLE_VPNPROFILE, null, values);
        if (insertId == -1) {
            return null;
        }
        profile.setId(insertId);
        return profile;
    }

    /**
     * Updates the given VPN profile in the database.
     * @param profile the profile to update
     * @return true if update succeeded, false otherwise
     */
    public boolean updateVpnProfile(VpnProfile profile) {
        long id = profile.getId();
        ContentValues values = ContentValuesFromVpnProfile(profile);
        return mDatabase.update(TABLE_VPNPROFILE, values, KEY_ID + " = " + id, null) > 0;
    }

    /**
     * Delete the given VPN profile from the database.
     * @param profile the profile to delete
     * @return true if deleted, false otherwise
     */
    public boolean deleteVpnProfile(VpnProfile profile) {
        if (profile == null) {
            return true;
        }
        String name = profile.getName();
        return mDatabase.delete(TABLE_VPNPROFILE, KEY_NAME + " = \"" + name + "\"", null) > 0;
    }

    /**
     * Get a single VPN profile from the database.
     * @param name name of vpn profile
     * @return the profile or null, if not found
     */
    public VpnProfile getVpnProfile(String name) {
        VpnProfile profile = null;
        Cursor cursor = null;
        try {
            cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, KEY_NAME + "=\"" + name + "\"", null, null,
                    null, null);
            if (cursor.moveToFirst()) {
                profile = VpnProfileFromCursor(cursor);
            }
        } finally {
            closeCursor(cursor);
        }
        return profile;
    }

    /**
     * Get a single VPN profile from the database.
     * @param id the ID of the VPN profile
     * @return the profile or null, if not found
     */
    public VpnProfile getVpnProfile(long id) {
        VpnProfile profile = null;
        Cursor cursor = null;
        try {
            cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, KEY_ID + "=" + id, null, null, null, null);
            if (cursor.moveToFirst()) {
                profile = VpnProfileFromCursor(cursor);
            }
        } finally {
            closeCursor(cursor);
        }
        return profile;
    }

    /**
     * Get a list of all VPN profiles stored in the database.
     * @return list of VPN profiles
     */
    public List<VpnProfile> getAllVpnProfiles() {
        List<VpnProfile> vpnProfiles = new ArrayList<VpnProfile>();

        Cursor cursor = null;
        try {
            cursor = mDatabase.query(TABLE_VPNPROFILE, ALL_COLUMNS, null, null, null, null, null);
            cursor.moveToFirst();
            while (!cursor.isAfterLast()) {
                VpnProfile vpnProfile = VpnProfileFromCursor(cursor);
                vpnProfiles.add(vpnProfile);
                cursor.moveToNext();
            }
        } finally {
            closeCursor(cursor);
        }
        return vpnProfiles;
    }

    private VpnProfile VpnProfileFromCursor(Cursor cursor) {
        VpnProfile profile = new VpnProfile();
        profile.setId(cursor.getLong(cursor.getColumnIndex(KEY_ID)));
        profile.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
        profile.setGateway(cursor.getString(cursor.getColumnIndex(KEY_GATEWAY)));
        profile.setVpnType(VpnType.fromIdentifier(cursor.getString(cursor.getColumnIndex(KEY_VPN_TYPE))));
        profile.setUsername(cursor.getString(cursor.getColumnIndex(KEY_USERNAME)));
        String password = cursor.getString(cursor.getColumnIndex(KEY_PASSWORD));
        if (StringUtils.isNotEmpty(password)) {
            profile.setPassword(password);
        }
        profile.setCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_CERTIFICATE)));
        profile.setUserCertificateAlias(cursor.getString(cursor.getColumnIndex(KEY_USER_CERTIFICATE)));
        profile.setMTU(getInt(cursor, cursor.getColumnIndex(KEY_MTU)));
        profile.setPort(getInt(cursor, cursor.getColumnIndex(KEY_PORT)));
        profile.setSplitTunneling(getInt(cursor, cursor.getColumnIndex(KEY_SPLIT_TUNNELING)));
        profile.setLocalId(cursor.getString(cursor.getColumnIndex(KEY_LOCAL_ID)));
        profile.setRemoteId(cursor.getString(cursor.getColumnIndex(KEY_REMOTE_ID)));
        profile = setFancyFonValuesOnProfileFromCursor(profile, cursor);
        return profile;
    }

    private VpnProfile setFancyFonValuesOnProfileFromCursor(VpnProfile profile, Cursor cursor) {
        profile.setCertificateId(cursor.getString(cursor.getColumnIndex(KEY_CERTIFICATE_ID)));
        profile.setAllowedApplications(
                convertFromString(cursor.getString(cursor.getColumnIndex(KEY_ALLOWED_APPLICATIONS))));
        profile.setLoggingLevel(cursor.getInt(cursor.getColumnIndex(KEY_LOGGING_LEVEL)));
        return profile;
    }

    private ContentValues ContentValuesFromVpnProfile(VpnProfile profile) {
        ContentValues values = new ContentValues();
        values.put(KEY_NAME, profile.getName());
        values.put(KEY_GATEWAY, profile.getGateway());
        values.put(KEY_VPN_TYPE, profile.getVpnType().getIdentifier());
        values.put(KEY_USERNAME, profile.getUsername());
        values.put(KEY_PASSWORD, profile.getPassword());
        values.put(KEY_CERTIFICATE, profile.getCertificateAlias());
        values.put(KEY_USER_CERTIFICATE, profile.getUserCertificateAlias());
        //not implemented in ff
        values.put(KEY_MTU, EMPTY_STRING);
        values.put(KEY_PORT, EMPTY_STRING);
        values.put(KEY_SPLIT_TUNNELING, SPLIT_TUNNELING_DEFAULT_VALUE);
        values.put(KEY_LOCAL_ID, EMPTY_STRING);
        values.put(KEY_REMOTE_ID, EMPTY_STRING);
        values = putFancyFonValues(values, profile);
        return values;

    }

    private ContentValues putFancyFonValues(ContentValues values, VpnProfile profile) {
        values.put(KEY_CERTIFICATE_ID, profile.getCertificateId());
        values.put(KEY_ALLOWED_APPLICATIONS, convertToString(profile.getAllowedApplications()));
        if (profile.getLoggingLevel() == 0) {
            profile.setLoggingLevel(1);
        }
        values.put(KEY_LOGGING_LEVEL, profile.getLoggingLevel());
        return values;
    }

    private String convertToString(ArrayList<String> list) {
        if (list == null) {
            return EMPTY_STRING;
        }
        StringBuilder buffer = new StringBuilder(list.size() * 16);
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            Object next = it.next();
            buffer.append(next);
            if (it.hasNext()) {
                buffer.append(",");
            }
        }
        return buffer.toString();
    }

    private ArrayList<String> convertFromString(String string) {
        if (string == null || string.length() == 0) {
            return new ArrayList<String>();
        }
        return new ArrayList<String>(Arrays.asList(string.split(",")));
    }

    private void closeCursor(Cursor cursor) {
        if (cursor != null) {
            cursor.close();
        }
    }

    private Integer getInt(Cursor cursor, int columnIndex) {
        return cursor.isNull(columnIndex) ? null : cursor.getInt(columnIndex);
    }
}