/** * MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface. * Copyright (C) 2012 Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /******************************************************************************\ * * This product was developed by * * SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO), * * a government company established under Brazilian law (5.615/70), * at Department of Development of Porto Alegre. * \******************************************************************************/ package serpro.mailarchiver.util; import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; public class Sqlite { public static final String PERMISSIONS_DATABASE_NAME = "permissions.db"; public static final String LOCALSERVER_DATABASE_NAME = "localserver.db"; private String browserArchiverPath = null; private static Sqlite instance = new Sqlite(); private static final Logger log = Logger.getLocalLogger(); public static Sqlite getInstance(){ try { Class.forName("org.sqlite.JDBC"); if(instance!=null){ return instance; } } catch (ClassNotFoundException ex) { log.error(ex); } return new Sqlite(); } public void setBrowserArchiverPath(String browserArchiverPath) { this.browserArchiverPath = browserArchiverPath; log.debug("Configurando origem do arquivamento gears..: " + browserArchiverPath); } public Map> listDatabasePaths(){ // System.out.println("Sqlite.listDatabasePaths sendo executado... "); log.debug("Sqlite.listDatabasePaths sendo executado... "); Map> result = new HashMap>(); try{ if(browserArchiverPath!=null){ String databasePermissions = GearsUtil.loadFilePaths(browserArchiverPath, PERMISSIONS_DATABASE_NAME); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePermissions); // System.out.println("Consultando databaseNames... "); log.debug("Consultando databaseNames... "); ResultSet rs = connection.createStatement(). executeQuery("select d.origin, d.basename from databasenames as d, " + "access a where d.origin=a.name " + "and d.isdeleted=0"); // System.out.println("Databases encontrados no path de arquivamento..: " + browserArchiverPath); List databasePaths = null; //armazenar os databasePaths por origin url while(rs.next()){ int index = rs.getString(1).indexOf("//"); String origin = null; String protocol = null; String databasePath = null; if(index!=-1){ if(rs.getString(1).contains("https")){ protocol = File.separatorChar + "https_443"; }else{ protocol = File.separatorChar + "http_80"; } index++; origin = browserArchiverPath + rs.getString(1).substring(index++, rs.getString(1).length()); origin += protocol; if(origin!=null && origin.length()>0 && !result.containsKey(origin)){ databasePaths = new ArrayList(); databasePath = GearsUtil.loadFilePaths(origin, rs.getString(2)); if(databasePath!=null){ databasePaths.add(databasePath); // System.out.println("Origem arquivamento..: " + origin + " DatabasePath do arquivamento..: " + databasePath); log.debug("Origem arquivamento..: " + origin + " DatabasePath do arquivamento..: " + databasePath); } result.put(origin, databasePaths); }else if(result.containsKey(origin)){ databasePath = GearsUtil.loadFilePaths(origin, rs.getString(2)); databasePaths.add(databasePath);//apenas adiciona databasePaths ao map // System.out.println("Origem arquivamento..: " + origin + " DatabasePath do arquivamento..: " + databasePath); log.debug("Origem arquivamento..: " + origin + " DatabasePath do arquivamento..: " + databasePath); } } } rs.close(); connection.close(); } }catch (SQLException ex) { log.error("Falha na obtenção dos databaseNames da origem de arquivamento gears..: " + browserArchiverPath, ex); } // System.out.println("Sqlite.listDatabasePaths sendo finalizado... "); log.debug("Sqlite.listDatabasePaths sendo finalizado... "); return result; } // valida se a estrutura de banco sqlite é utilizada pela suite expresso public boolean isExpressoDatabase(String databasePath){ // System.out.println("Sqlite.isExpressoDatabase sendo executado... "); log.debug("Sqlite.isExpressoDatabase sendo executado... "); boolean result = false; try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); // System.out.println("Sqlite Driver Version..: " + connection.getMetaData().getDriverVersion()); // System.out.println("Validando estrutura da tabela.: " + databasePath + "... "); log.debug("Validando estrutura da tabela.: " + databasePath + "... "); //#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ ResultSet rs = connection.createStatement(). executeQuery( "select name from sqlite_master where type='table' order by name;"); int index=0; while(rs.next()){ if(rs.getString(1).equalsIgnoreCase("anexo") || rs.getString(1).equalsIgnoreCase("folder") || rs.getString(1).equalsIgnoreCase("mail")){ index++; if(index==3) break; } } if(index == 3){ // System.out.println("Estrutura da tabela foi validada com sucesso! "); log.debug("Estrutura da tabela foi validada com sucesso! "); createArchiveImporter(connection, databasePath); //cria a tabela de controle caso ainda não exista result = true; }else{ // System.out.println("Estrutura da tabela inválida! "); log.debug("Estrutura da tabela inválida! "); } rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na validação da estrutura sqlite referente ao databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.isExpressoDatabase sendo finalizado... "); log.debug("Sqlite.isExpressoDatabase sendo finalizado... "); return result; } public boolean isUserDatabase(String databasePath, String user){ System.out.println("Sqlite.isUserDatabase sendo executado... "); log.debug("Sqlite.isUserDatabase sendo executado... "); boolean result = false; try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement().executeQuery("select count(*) from folder where uid_usuario='" + user + "'"); System.out.println("Consultando folders para o usuário " + user + " ... "); log.debug("Consultando folders para o usuário " + user + " ... "); int folders = Integer.parseInt(rs.getString(1)); if(folders > 0){ result = true; } rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha ao consultar permissão de usuário em folders para o databasePath..: " + databasePath, ex); } System.out.println("Sqlite.isUserDatabase sendo finalizado... "); log.debug("Sqlite.isUserDatabase sendo finalizado... "); return result; } // seleciona todos os folders(names) dos folders encontrados public Set listFolders(String databasePath, String user){ // System.out.println("Sqlite.listFolders sendo executado... "); log.debug("Sqlite.listFolders sendo executado... "); Set result = new HashSet(); try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement().executeQuery("select folder from folder where uid_usuario='" + user + "' order by rowid"); // System.out.println("Consultando folders... "); log.debug("Consultando folders... "); while(rs.next()) result.add(rs.getString(1)); rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na listagem de folder para o databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.listFolders sendo finalizado... "); log.debug("Sqlite.listFolders sendo finalizado... "); return result; } // seleciona todos os folders(names) já criados pelo mailarchiver // por usuário e por mailArcID public Set listArchivedFolders(String databasePath, String mailArcID, String user){ // System.out.println("Sqlite.listArchivedFolders sendo executado... "); log.debug("Sqlite.listArchivedFolders sendo executado... "); Set result = new HashSet(); try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement().executeQuery("select folder from user_archive_importer " + "where imported='true' and uid_usuario='" + user + "' order by rowid"); // System.out.println("Consultando folders arquivados... "); log.debug("Consultando folders arquivados... "); while(rs.next()) result.add(rs.getString(1)); rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na listagem de folder arquivado para o databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.listArchivedFolders sendo finalizado... "); log.debug("Sqlite.listArchivedFolders sendo finalizado... "); return result; } // carrega o total de mensagens por databasePath public Integer getTotalMessages(String databasePath, String mailArcID, String user){ // System.out.println("Sqlite.getTotalMessages sendo executado... "); log.debug("Sqlite.getTotalMessages sendo executado... "); Integer result = 0; try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement(). executeQuery("select count(*) rowid from mail where rowid not in(" + "select archive.mailid from user_archive_importer as archive, mail as mail " + "where mail.rowid = archive.mailid and archive.uid_usuario='" + user + "' " + "and archive.mailarcid='" + mailArcID + "') and uid_usuario='" + user + "'"); while(rs.next()){ result = Integer.parseInt(rs.getString(1)); } // System.out.println(result + " emails contabilizados para o databasePath " + databasePath); log.debug(result + " emails contabilizados para o databasePath " + databasePath); rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na contagem de emails para o databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.getTotalMessages sendo finalizado... "); log.debug("Sqlite.getTotalMessages sendo finalizado... "); return result; } // carrega o total de mensagens validas por databasePath para importação pelo mailarchiver public Integer getTotalValidMessages(String databasePath, String mailArcID, String user){ // System.out.println("Sqlite.getTotalValidMessages sendo executado... "); log.debug("Sqlite.getTotalValidMessages sendo executado... "); Integer result = 0; try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement().executeQuery("select count(*) rowid from user_archive_importer " + "where imported='false' and uid_usuario='" + user + "' and mailarcid='" + mailArcID + "'"); while(rs.next()){ result = Integer.parseInt(rs.getString(1)); } // System.out.println(result + " emails válidos contabilizados para o databasePath " + databasePath); log.debug(result + " emails válidos contabilizados para o databasePath " + databasePath); rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na contagem de emails para o databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.getTotalValidMessages sendo finalizado... "); log.debug("Sqlite.getTotalValidMessages sendo finalizado... "); return result; } // leitura dos dados da tabela mail a serem importados por folder public Map> listMessages(String databasePath, String folder, String mailArcID, String user){ // System.out.println("Sqlite.listMessages sendo executado... "); log.debug("Sqlite.listMessages sendo executado... "); Map> result = new HashMap>(); try{ Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement(). executeQuery("select m.rowid, m.subject, m.mail from mail as m, folder as f " + "where m.id_folder = f.rowid and f.folder ='" + folder + "' " + "and m.rowid not in(select archive.mailid from " + "user_archive_importer as archive, mail as mail " + "where mail.rowid = archive.mailid " + "and archive.uid_usuario='" + user + "' " + "and archive.mailarcid='" + mailArcID + "') and m.uid_usuario='" + user + "'"); // System.out.println("Consultando emails... "); log.debug("Consultando emails... "); // int messages = 0; while(rs.next()) { Map values = new HashMap(); values.put(rs.getString(2), rs.getString(3)); result.put(rs.getString(1), values); // messages++; } rs.close(); connection.close(); }catch (SQLException ex) { log.error("Falha na listagem de mensagens do folder " + folder + " referentes ao databasePath..: " + databasePath, ex); } // System.out.println("Sqlite.listMessages sendo finalizado... "); log.debug("Sqlite.listMessages sendo finalizado... "); return result; } // carrega o filepath extraido da urlExportFile passada como parâmetro public String getResponseBodiesFilePath(String urlExportFile) throws SQLException{ // System.out.println("Sqlite.getResponseBodiesFilePath sendo executado... "); log.debug("Sqlite.getResponseBodiesFilePath sendo executado... "); String result = null; String databasePath = GearsUtil.loadFilePaths(browserArchiverPath, LOCALSERVER_DATABASE_NAME); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement(). executeQuery("select resp.filepath from responsebodies as resp, entries as ent " + "where ent.payloadid=resp.bodyid " + "and ent.url like '%" + urlExportFile + "'"); if(rs.getString(1)!=null && rs.getString(1).length()>0){ result = rs.getString(1); } rs.close(); connection.close(); // System.out.println("Sqlite.getResponseBodiesFilePath sendo finalizado... "); log.debug("Sqlite.getResponseBodiesFilePath sendo finalizado... "); //Ajusta o caminho correto para a carga do arquivo fonte da mensagem, de acordo com o sistema operacional em uso //implementado para possibilitar a importação de mensagens caso o usuário copie o seu Gears do Windows para o Linux result = result.replace('\\', '/'); log.debug("ImportGears: ajustado o URLFilePath de acordo com o sistema operacional ::'" + result + "'"); return result; } // cria tabela de controle de importação de emails do google gears public void createArchiveImporter(Connection connection,String databasePath){ // System.out.println("Sqlite.createArchiveImporter sendo executado... "); log.debug("Sqlite.createArchiveImporter sendo executado... "); try{ // Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); // // System.out.println("Criando tabela de controle archive_importer em..: " + databasePath); log.debug("Criando tabela de controle user_archive_importer... "); connection.createStatement(). executeUpdate("create table if not exists user_archive_importer(mailid text,mailarcid text," + "folder text,filepath text,imported boolean,import_date text,uid_usuario text,unique(mailid,mailarcid,uid_usuario))"); // System.out.println("Tabela de controle archive_importer criada. "); log.debug("Tabela de controle user_archive_importer criada. "); // connection.close(); }catch (SQLException ex) { log.error("Falha na criação da tabela de controle de arquivamento user_archive_importer", ex); } // System.out.println("Sqlite.createArchiveImporter sendo finalizado... "); log.debug("Sqlite.createArchiveImporter sendo finalizado... "); } // insere registro de controle de importação de emails do google gears // utiliza conexão já ativa public boolean insertMessageParameters(String databasePath, String folder, String mailId, String mailarcId, String filePath, String user) throws SQLException{ // System.out.println("Sqlite.insertMessageParameters sendo executado... "); log.debug("Sqlite.insertMessageParameters sendo executado... "); boolean result = false; // System.out.println("Inserindo registro na tabela de controle archive_importer... "); log.debug("Inserindo registro na tabela de controle user_archive_importer... "); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); connection.createStatement(). executeUpdate("BEGIN TRANSACTION; " + "insert into user_archive_importer values('" + mailId + "','" + mailarcId + "','" + folder + "','" + filePath + "','" + false + "','" + new SimpleDateFormat("dd-MMMM-yyyy HH:mm:ss"). format(new Date()) + "','" + user + "'); " + "COMMIT;"); result = true; // System.out.println("Tabela de controle archive_importer atualizada. "); log.debug("Tabela de controle user_archive_importer atualizada. "); connection.close(); // System.out.println("Sqlite.insertMessageParameters sendo finalizado... "); log.debug("Sqlite.insertMessageParameters sendo finalizado... "); return result; } // atualiza tabela de controle de importação de emails do google gears após importação pelo mailarchiver public void updateMessageParameters(String databasePath, String mailId, String mailarcId, String user) throws SQLException{ // System.out.println("Sqlite.updateMessageParameters sendo executado... "); log.debug("Sqlite.updateMessageParameters sendo executado... "); // System.out.println("Atualizando a tabela de controle archive_importer ... "); log.debug("Atualizando a tabela de controle user_archive_importer ... "); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); connection.createStatement(). executeUpdate("BEGIN TRANSACTION; " + "update user_archive_importer set imported='true', import_date='" + new SimpleDateFormat("dd-MMMM-yyyy HH:mm:ss").format(new Date()) + "' " + "where mailid='" + mailId + "' and uid_usuario='" + user + "' " + "and mailarcid='" + mailarcId + "'; " + "COMMIT;"); // System.out.println("Tabela de controle archive_importer atualizada. "); log.debug("Tabela de controle user_archive_importer atualizada. "); connection.close(); // System.out.println("Sqlite.updateMessageParameters sendo finalizado... "); log.debug("Sqlite.updateMessageParameters sendo finalizado... "); } // deleta os registros da tabela de controle de importação de emails do google gears para o mailarcid passado public void deleteMessageParameters(String databasePath, String mailarcId, String user) throws SQLException{ // System.out.println("Sqlite.deleteMessageParameters sendo executado... "); log.debug("Sqlite.deleteMessageParameters sendo executado... "); // System.out.println("Excluindo registros da tabela de controle archive_importer ... "); log.debug("Excluindo registros da tabela de controle user_archive_importer ... "); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); connection.createStatement(). executeUpdate("delete from user_archive_importer where mailarcid='" + mailarcId + "' and uid_usuario='" + user + "'"); // System.out.println("Tabela de controle archive_importer atualizada. "); log.debug("Tabela de controle user_archive_importer atualizada. "); connection.close(); // System.out.println("Sqlite.deleteMessageParameters sendo finalizado... "); log.debug("Sqlite.deleteMessageParameters sendo finalizado... "); } // lista os registros da tabela de controle de importação de emails do google gears para o mailarcid passado public LinkedList listMessageParameters(String databasePath, String mailArcId, String user){ // System.out.println("Sqlite.listMessageParameters sendo executado... "); log.debug("Sqlite.listMessageParameters sendo executado... "); LinkedList result = new LinkedList();//manter a ordem de folder try{ // System.out.println("Listando registros da tabela de controle archive_importer ... "); log.debug("Listando registros da tabela de controle user_archive_importer ... "); Connection connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); ResultSet rs = connection.createStatement().executeQuery("select archive.folder, archive.mailid, archive.filepath, m.header, m.unseen from user_archive_importer as archive, mail as m " + "where archive.mailid=m.rowid and archive.mailarcid='" + mailArcId + "' and archive.imported='false' and archive.uid_usuario='" + user + "' order by archive.folder"); while(rs.next()){ result.add(new String[]{rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5)}); } connection.close(); }catch (SQLException ex) { log.error("Falha na listagem de registros da tabela user_archive_importer para o mailArcId..: " + mailArcId, ex); } // System.out.println("Sqlite.listMessageParameters sendo finalizado... "); log.debug("Sqlite.listMessageParameters sendo finalizado... "); return result; } }