Source

KPDataSave / KPDataSave / KPDataSaveExt.cs

Full commit
/*
    KPDataSave - KeePass plugin which saves database in Dropbox service
    Copyright (C) 2011-2012 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 _mHost;
        // Меню
        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(CurrentDomainAssemblyResolve);

            _mHost = host;

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

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

            return true;
        }

        // Грузим сборку из ресурсов приложения
        private static Assembly CurrentDomainAssemblyResolve(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 MainWindowFileOpened(object sender, KeePass.Forms.FileOpenedEventArgs e)
        {
            // Пописываемся на событие по завершению сохранения данных в файл
            _mHost.MainWindow.FileSaved += new EventHandler<KeePass.Forms.FileSavedEventArgs>(MainWindowFileSaved);
        }

        // Событие сохранения данных
        private void MainWindowFileSaved(object sender, KeePass.Forms.FileSavedEventArgs e)
        {
            // Информация об акке
            AccountState account = AccountState.Deserialize(_mHost);
            if (account == null)
                return;

            // Сообщение в статуc баре
            _mHost.MainWindow.SetStatusEx("Saving in Dropbox...");
            // Отображаем прогресс бар
            _mHost.MainWindow.MainProgressBar.Visible = true;
            _mHost.MainWindow.MainProgressBar.Style = ProgressBarStyle.Marquee;
            // Блокируем окно
            _mHost.MainWindow.UIBlockInteraction(true);
            // Путь к файлу базы
            string dbFile = _mHost.Database.IOConnectionInfo.Path;
            DropboxClient client = new DropboxClient("hhekhlyshoqxt5s", "h0oh21e8y2seixx", account.Token, account.Secret);
            // Сохранение файла базы на сервере Dropbox
            FileInfo file = new FileInfo(dbFile);

            // Поток для выполнения асинхронной загрузки файла
            new Thread(() => UploadFileAsync(client, file, account.Path)).Start();
        }

        // Клик на пункте меню настроек плагина
        private void TsMenuItemClick(object sender, EventArgs e)
        {
            // Вызываем менеджер состояний
            new Forms.StateControl(_mHost);
        }

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

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