Source

KPDataSave / KPDataSave / KPDataSaveExt.cs

Full commit
/*
    KPDataSave - KeePass plugin which saves database in Dropbox service
    Copyright (C) 2011 HexRx

    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 3 of the License, or
    (at your option) any later version.

    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.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Reflection;

// KeePass
using KeePass.Plugins;

using DropboxAPI;

namespace KPDataSave
{
    public sealed class KPDataSaveExt : Plugin
    {
        private IPluginHost m_host;
        // Меню
        private ToolStripSeparator tsSep;
        private ToolStripMenuItem tsMenuItem;
        // Обновление плагина
        public override string UpdateUrl
        {
            get { return "http://pastebin.com/raw.php?i=eBhcLPzq"; }
        }
        // Иконка плагина
        public override System.Drawing.Image SmallIcon
        {
            get { return Properties.Resources.dropbox_16x16; }
        }

        // Инициализация
        public override bool Initialize(IPluginHost host)
        {
            // Динамическая загрузка сборок
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

            m_host = host;

            ToolStripItemCollection tsMenu = m_host.MainWindow.ToolsMenu.DropDownItems;
            // Разделитель
            tsSep = new ToolStripSeparator();
            tsMenu.Add(tsSep);
            // Пункт меню KPDataSave
            tsMenuItem = new ToolStripMenuItem("KPDataSave", Properties.Resources.dropbox_16x16);
            tsMenuItem.Click += new EventHandler(tsMenuItem_Click);
            tsMenu.Add(tsMenuItem);

            // Подписываемся на открытия базы
            m_host.MainWindow.FileOpened += new EventHandler<KeePass.Forms.FileOpenedEventArgs>(MainWindow_FileOpened);

            return true;
        }

        // Грузим сборку из ресурсов приложения
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            if (args.Name.Contains("RestSharp"))
            {
                byte[] data = Properties.Resources.RestSharpMerge;
                // Разархивируем сборку
                SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
                MemoryStream istream = new MemoryStream(data);
                MemoryStream ostream = new MemoryStream();
                // Считываем настройки архивации
                byte[] properties = new byte[5];
                if (istream.Read(properties, 0, 5) != 5)
                    throw new PlgxException("KPDataSave Exception: Unpacked prop");
                decoder.SetDecoderProperties(properties);
                // Получаем оригинальный размер
                long outSize = 0;
                for (int i = 0; i < 8; i++)
                {
                    int v = istream.ReadByte();
                    if (v < 0)
                        throw new PlgxException("KPDataSave Exception: Unpacked size");
                    outSize |= ((long)(byte)v) << (8 * i);
                }
                decoder.Code(istream, ostream, -1, outSize, null);
                return Assembly.Load(ostream.ToArray());
            }
            return null;
        }

        // Событие открытия базы
        private void MainWindow_FileOpened(object sender, KeePass.Forms.FileOpenedEventArgs e)
        {
            // Пописываемся на событие по завершению сохранения данных в файл
            m_host.MainWindow.FileSaved += new EventHandler<KeePass.Forms.FileSavedEventArgs>(MainWindow_FileSaved);
        }

        // Событие сохранения данных
        private void MainWindow_FileSaved(object sender, KeePass.Forms.FileSavedEventArgs e)
        {
            // Информация об акке
            AccountState acc;
            try
            {
                acc = Config.GetAccountState(m_host);
            }
            catch (NullReferenceException)
            {
                // Если не произведен вход под акком, выходим из этого метода
                return;
            }
            // Сообщение в статуc баре
            m_host.MainWindow.SetStatusEx("Saving in Dropbox...");
            // Отображаем прогресс бар
            m_host.MainWindow.MainProgressBar.Visible = true;
            m_host.MainWindow.MainProgressBar.Style = ProgressBarStyle.Marquee;
            // Блокируем окно
            m_host.MainWindow.UIBlockInteraction(true);
            // Путь к файлу базы
            string db_file = m_host.Database.IOConnectionInfo.Path;
            DropboxClient client = new DropboxClient("hhekhlyshoqxt5s", "h0oh21e8y2seixx", acc.Token, acc.Secret);
            // Сохранение файла базы на сервере Dropbox
            FileInfo file = new FileInfo(db_file);
            // Поток для выполнения асинхронной загрузки файла
            new Thread(delegate() { this.UploadFileAsync(client, file); }).Start();
        }

        // Клик на пункте меню настроек плагина
        void tsMenuItem_Click(object sender, EventArgs e)
        {
            // Форма настроек
            using (Forms.KPDataSave ds = new Forms.KPDataSave(m_host))
            {
                ds.ShowDialog();
            }
        }

        // Завершение приложения
        public override void Terminate()
        {
            ToolStripItemCollection tsMenu = m_host.MainWindow.ToolsMenu.DropDownItems;
            // Сносим пункты меню
            tsMenu.Remove(tsSep);
            tsMenu.Remove(tsMenuItem);
        }

        // Асинхронная загрузка
        private void UploadFileAsync(DropboxClient client, FileInfo file)
        {
            // Выполняем загрузку файла
            if (client.UploadFile("/", file))
                m_host.MainWindow.SetStatusEx("Dropbox save complete!");
            else
                m_host.MainWindow.SetStatusEx("Dropbox save error!");
            // Скрываем прогресс
            m_host.MainWindow.MainProgressBar.Visible = false;
            // Разблокируем окно
            m_host.MainWindow.UIBlockInteraction(false);
        }
    }
}