/* * Copyright (C) 2005 Kouji TAKAO * * 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. * * 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 Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include "gpass/entry.h" #include "gpass/entry-factory.h" #include "gpass/file04.h" #include "gpass/file.h" #include "gpass/error.h" static GError * read_file_044(const gchar *path, const gchar *password, GPassEntry **entries) { GPassFile04 *file; GPassEntryFactory *factory; GError *error; error = gpass_file04_open(&file, path, password); if (error != NULL) { return error; } factory = g_object_new(GPASS_TYPE_ENTRY_FACTORY, NULL); error = gpass_file04_read(file, factory, entries); g_object_unref(factory); gpass_file04_close(file); return error; } #if 0 static GError * write_file_044(const gchar *path, const gchar *password, GPassEntry *entries) { GPassFile04 *file; GError *error; error = gpass_file04_create(path, password); if (error != NULL) { return error; } error = gpass_file04_open(&file, path, password); if (error != NULL) { return error; } error = gpass_file04_write(file, entries); gpass_file04_close(file); return error; } #endif static GError * read_file(const gchar *path, const gchar *password, GPassEntry **entries) { GPassFile *file; GPassEntryFactory *factory; GError *error; error = gpass_file_open(&file, path, password); if (error != NULL) { return error; } factory = g_object_new(GPASS_TYPE_ENTRY_FACTORY, NULL); error = gpass_file_read(file, factory, entries); g_object_unref(factory); gpass_file_close(file); return error; } static GError * write_file_100(const gchar *path, const gchar *password, GPassEntry *entries) { GPassFile *file; GError *error; error = gpass_file_create(path, password); if (error != NULL) { return error; } error = gpass_file_open(&file, path, password); if (error != NULL) { return error; } error = gpass_file_write_with_version(file, entries, "1.0.0"); gpass_file_close(file); return error; } static GError * write_file_110(const gchar *path, const gchar *password, GPassEntry *entries) { GPassFile *file; GError *error; error = gpass_file_create(path, password); if (error != NULL) { return error; } error = gpass_file_open(&file, path, password); if (error != NULL) { return error; } error = gpass_file_write(file, entries); gpass_file_close(file); return error; } typedef struct { GHashTable *hash; } ConverterContext; typedef struct { const gchar *version; GError *(*read)(const gchar *password, const gchar *path, GPassEntry **entries); GError *(*write)(const gchar *password, const gchar *path, GPassEntry *entries); } ConverterEntry; static ConverterEntry converter_entries[] = { { "0.4.4", read_file_044, NULL }, { "0.5.0rc1", read_file, write_file_100 }, { "head", read_file, write_file_110 } }; static void init_converter(ConverterContext *context) { gint i; context->hash = g_hash_table_new(g_str_hash, g_str_equal); for (i = 0; i < G_N_ELEMENTS(converter_entries); i++) { g_hash_table_insert(context->hash, (gpointer) converter_entries[i].version, &converter_entries[i]); } } static void finalize_converter(ConverterContext *context) { g_hash_table_destroy(context->hash); g_free(context); } static void list_converters(void) { gint i; const gchar *format = _("%-15s %-5s %-5s\n"); gpass_error_locale_printf(format, _("Version"), _("Read"), _("Write")); for (i = 0; i < G_N_ELEMENTS(converter_entries); i++) { ConverterEntry *entry = &converter_entries[i]; gpass_error_locale_printf(format, entry->version, entry->read == NULL ? _("No") : _("Yes"), entry->write == NULL ? _("No") : _("Yes")); } } static GError * read_master_password(gchar **password) { int status; gchar buffer[1024]; fprintf(stdout, "Master Password: "); fflush(stdout); status = system("stty -echo"); if (WEXITSTATUS(status) != 0) { GError *error = NULL; g_set_error(&error, 0, 0, _("could not run stty\n")); return error; } if (fgets(buffer, 1024, stdin) != NULL) { *password = g_strdup(g_strchomp(buffer)); } system("stty echo"); fprintf(stdout, "\n"); fflush(stdout); return NULL; } #define DEFAULT_FROM_VERSION "0.5.0rc1" #define DEFAULT_TO_VERSION "head" int main(int argc, char *argv[]) { ConverterContext *cvt_ctx; ConverterEntry *read_entry, *write_entry; gchar *password; GPassEntry *entries; const gchar *from_path, *to_path; const gchar *from_version = DEFAULT_FROM_VERSION; const gchar *to_version = DEFAULT_TO_VERSION; gboolean list = FALSE; gboolean quiet = FALSE; GOptionEntry opt_entries[] = { { "from", 'f', 0, G_OPTION_ARG_STRING, &from_version, N_("version of convert from"), "VERSION" }, { "to", 't', 0, G_OPTION_ARG_STRING, &to_version, N_("version of convert to"), "VERSION" }, { "list", 'l', 0, G_OPTION_ARG_NONE, &list, N_("list all supported versions"), NULL }, { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet, N_("no progress indicator"), NULL }, { NULL } }; GOptionContext *opt_ctx; GError *error = NULL; #ifdef ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(PACKAGE); #endif g_type_init(); opt_ctx = g_option_context_new(_(" \n" "file format converter for GPass")); g_option_context_add_main_entries(opt_ctx, opt_entries, GETTEXT_PACKAGE); g_option_context_set_ignore_unknown_options(opt_ctx, FALSE); g_option_context_parse(opt_ctx, &argc, &argv, &error); g_option_context_free(opt_ctx); if (error != NULL) { gpass_error_show_and_exit(error); } if (list) { list_converters(); exit(0); } if (argc != 3) { fprintf(stderr, _("invalid argument\n")); exit(1); } from_path = argv[1]; to_path = argv[2]; cvt_ctx = g_new0(ConverterContext, 1); init_converter(cvt_ctx); read_entry = g_hash_table_lookup(cvt_ctx->hash, from_version); if (read_entry == NULL || read_entry->read == NULL) { printf(_("not supports for read: %s\n"), from_version); exit(1); } write_entry = g_hash_table_lookup(cvt_ctx->hash, to_version); if (write_entry == NULL || write_entry->write == NULL) { printf(_("not supports for write: %s\n"), to_version); exit(1); } if (!g_file_test(from_path, G_FILE_TEST_EXISTS)) { printf(_("not exist for read: %s\n"), from_path); exit(1); } if (g_file_test(to_path, G_FILE_TEST_EXISTS)) { printf(_("already exist for write: %s\n"), to_path); exit(1); } error = read_master_password(&password); if (error != NULL) { gpass_error_show_and_exit(error); } if (!quiet) { fprintf(stdout, _("reading %s(version %s)... "), from_path, from_version); fflush(stdout); } error = read_entry->read(from_path, password, &entries); if (error != NULL) { gpass_error_show_and_exit(error); } if (!quiet) { fprintf(stdout, _("done\n")); fprintf(stdout, _("writing %s(version %s)... "), to_path, to_version); fflush(stdout); } write_entry->write(to_path, password, entries); if (error != NULL) { gpass_error_show_and_exit(error); } if (!quiet) { fprintf(stdout, _("done\n")); } g_object_unref(entries); g_free(password); finalize_converter(cvt_ctx); return 0; }