Source

KPDataSave / DropboxSave / DropboxSaveExt.cs

/*
    DropboxSave - KeePass plugin which save 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;

// DropNet
using DropNet;

namespace DropboxSave
{
    public sealed class DropboxSaveExt : Plugin
    {
        private IPluginHost m_host;
        // Меню
        private ToolStripSeparator tsSep;
        private ToolStripMenuItem tsMenuItem;

        // Инициализация
        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);
            // DropboxSave
            tsMenuItem = new ToolStripMenuItem("DropboxSave", 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("DropNet"))
            {
                byte[] data = Properties.Resources.DropNetMerge;
                // Разархивируем сборку
                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("DropboxSave Exception:78");
                decoder.SetDecoderProperties(properties);
                // Получаем оригинальный размер
                long outSize = 0;
                for (int i = 0; i < 8; i++)
                {
                    int v = istream.ReadByte();
                    if (v < 0)
                        throw new PlgxException("DropboxSave Exception:86");
                    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)
        {
            // Проверяем существование информации об аккаунте в конифгах
            if (Config.IsAccountState(m_host))
            {
                // Пописываемся на событие по завершению сохранения данных в файл
                m_host.MainWindow.FileSaved += new EventHandler<KeePass.Forms.FileSavedEventArgs>(MainWindow_FileSaved);
            }
        }

        // Событие сохранения данных
        private void MainWindow_FileSaved(object sender, KeePass.Forms.FileSavedEventArgs e)
        {
            // Сообщение в стату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);
            // Информация об акке
            AccountState acc = Config.GetAccountState(m_host);
            // Путь к файлу базы
            string db_file = m_host.Database.IOConnectionInfo.Path;
            DropNetClient client = new DropNetClient("hhekhlyshoqxt5s", "h0oh21e8y2seixx", acc.Token, acc.Secret);
            // Сохранение файла базы на сервере Dropbox
            FileInfo file = new FileInfo(db_file);

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

        // Клик на пункте меню DropboxSave
        void tsMenuItem_Click(object sender, EventArgs e)
        {
            new Forms.DropboxSave(m_host).ShowDialog();//.Show(m_host.MainWindow);
        }

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

        // Асинхронная загрузка
        private void UploadFileAsync(DropNetClient client, FileInfo file)
        {
            // Превращаем файл в массив байт
            byte[] content = File.ReadAllBytes(file.FullName);
            // Выполняем загрузку файла
            DropNet.Models.DropNetResult result = client.UploadFile("/", file.Name, content);
            if (result.StatusCode == System.Net.HttpStatusCode.OK)
                m_host.MainWindow.SetStatusEx("Dropbox save complete!");
            // Скрываем прогресс
            m_host.MainWindow.MainProgressBar.Visible = false;
            // Разблокируем окно
            m_host.MainWindow.UIBlockInteraction(false);
        }
    }
}