• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

csv2yapet/csvimport.cc

Go to the documentation of this file.
00001 // $Id: csvimport.cc 3344 2010-09-17 19:26:56Z java $
00002 //
00003 // Copyright (C) 2009-2010  Rafael Ostertag
00004 //
00005 // This file is part of YAPET.
00006 //
00007 // YAPET is free software: you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the Free Software
00009 // Foundation, either version 3 of the License, or (at your option) any later
00010 // version.
00011 //
00012 // YAPET is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00015 // details.
00016 //
00017 // You should have received a copy of the GNU General Public License along with
00018 // YAPET.  If not, see <http://www.gnu.org/licenses/>.
00019 //
00020 // Additional permission under GNU GPL version 3 section 7
00021 //
00022 // If you modify this program, or any covered work, by linking or combining it
00023 // with the OpenSSL project's OpenSSL library (or a modified version of that
00024 // library), containing parts covered by the terms of the OpenSSL or SSLeay
00025 // licenses, Rafael Ostertag grants you additional permission to convey the
00026 // resulting work.  Corresponding Source for a non-source form of such a
00027 // combination shall include the source code for the parts of OpenSSL used as
00028 // well as that of the covered work.
00029 //
00030 
00031 #ifdef HAVE_CONFIG_H
00032 # include <config.h>
00033 #endif
00034 
00035 #ifdef HAVE_UNISTD_H
00036 # include <unistd.h>
00037 #endif
00038 
00039 #ifdef HAVE_STRING_H
00040 # include <string.h>
00041 #endif
00042 
00043 #ifdef HAVE_STDIO_H
00044 # include <stdio.h>
00045 #endif
00046 
00047 #ifdef HAVE_IOSTREAM
00048 # include <iostream>
00049 #endif
00050 
00051 #ifdef HAVE_FSTREAM
00052 # include <fstream>
00053 #endif
00054 
00055 #include "csvimport.h"
00056 #include <structs.h>
00057 #include <file.h>
00058 
00066 void
00067 CSVImport::cleanupValue (std::string& str) {
00068     if (str.length() == 0) return;
00069 
00070     if (str.at (0) == '"')
00071         str = str.erase (0, 1);
00072 
00073     if (str.at (str.length() - 1) == '"')
00074         str = str.erase (str.length() - 1, 1);
00075 
00076     std::string::size_type pos = 0;
00077 
00078     while ( ( pos = str.find ("\"\"", pos) ) != std::string::npos ) {
00079         str.erase (pos, 1);
00080 
00081         if (pos + 1 < str.length() )
00082             pos++;
00083     }
00084 }
00085 
00093 void
00094 CSVImport::logError (unsigned long lno, const std::string& errmsg) {
00095     if (verbose) {
00096         std::cout << 'e';
00097         std::cout.flush();
00098     }
00099 
00100     LogEntry tmp;
00101     tmp.lineno = lno;
00102     tmp.message = errmsg;
00103     logs.push_back (tmp);
00104     had_errors = true;
00105     num_errors++;
00106 }
00107 
00121 CSVImport::CSVImport (std::string src, std::string dst, char sep, bool verb) throw (std::runtime_error) :
00122         srcfile (src),
00123         dstfile (dst),
00124         separator (sep),
00125         verbose (verb),
00126         had_errors (false),
00127         num_errors (0) {
00128     if (access (srcfile.c_str(), R_OK | F_OK) == -1)
00129         throw std::runtime_error ("Cannot access " + srcfile);
00130 }
00131 
00137 void
00138 CSVImport::import (const char* pw) throw (std::exception) {
00139     std::ifstream csvfile (srcfile.c_str() );
00140 
00141     if (!csvfile)
00142         throw std::runtime_error ("Cannot open " + srcfile);
00143 
00144     // the max line length. Computed from the field sizes of a YAPET password
00145     // record.
00146     const int max_len = YAPET::NAME_SIZE +
00147                         YAPET::HOST_SIZE +
00148                         YAPET::USERNAME_SIZE +
00149                         YAPET::PASSWORD_SIZE +
00150                         YAPET::COMMENT_SIZE +
00151                         // for the separators
00152                         NUM_SEPARATORS;
00153     // used for logging purpose
00154     const unsigned int num_fields = NUM_SEPARATORS + 1;
00155     char num_fields_str[5];
00156     snprintf (num_fields_str, 5, "%u", num_fields);
00157     YAPET::Key key (pw);
00158     YAPET::File yapetfile (dstfile, key, true);
00159     std::list<YAPET::PartDec> list;
00160     char line[max_len];
00161     // Holds the line number count
00162     unsigned long lineno = 0;
00163     // Flag indicating whether we're in a quote or not
00164     bool inquote = false;
00165     // Array holding the field values of the csv file
00166     std::string field_values[num_fields];
00167     // Integer indicating which field has to be filled
00168     int current_field = 0;
00169     // Number of delimiters found per line
00170     int num_sep_found = 0;
00171     // The iterator for scanning the line character by character
00172     std::string::size_type it = 0;
00173 
00174     while (csvfile.getline (line, max_len) ) {
00175         lineno++;
00176         std::string l (line);
00177         // integer pointing to the last delimiter found
00178         std::string::size_type last_sep = 0;
00179 
00180         if (!inquote) {
00181             current_field = 0;
00182             num_sep_found = 0;
00183 
00184             for (unsigned int i = 0; i < num_fields; i++)
00185                 field_values[i].clear();
00186         }
00187 
00188         // Indicate scanning error
00189         bool scan_error = false;
00190 
00191         for (it = 0; it < l.length(); it++) {
00192             // Flip the inquote flag when encountering a double quote
00193             if (l.at (it) == '"') {
00194                 inquote = !inquote;
00195             }
00196 
00197             if (!inquote && (l.at (it) == separator) ) {
00198                 num_sep_found++;
00199 
00200                 if (num_sep_found > NUM_SEPARATORS) {
00201                     std::string tmp ("Too many fields. Expected ");
00202                     tmp += num_fields_str;
00203                     tmp += " fields.";
00204                     logError (lineno, tmp );
00205                     scan_error = true;
00206                     break;
00207                 }
00208 
00209                 field_values[current_field] = l.substr (last_sep, it - last_sep);
00210                 cleanupValue (field_values[current_field]);
00211                 last_sep = it + 1;
00212                 current_field++;
00213             }
00214         }
00215 
00216         if (scan_error) continue;
00217 
00218         // Make sure the last field will be extracted too, but check if the
00219         // last separator has any value followed.
00220         if (it > last_sep) {
00221             field_values[current_field] = l.substr (last_sep, it - last_sep);
00222             cleanupValue (field_values[current_field]);
00223         }
00224 
00225         if (!inquote && (num_sep_found < NUM_SEPARATORS) ) {
00226             std::string tmp ("Too few fields. Expected ");
00227             tmp += num_fields_str;
00228             tmp += " fields.";
00229             logError (lineno, tmp );
00230             continue;
00231         }
00232 
00233         if (!inquote && (num_sep_found == NUM_SEPARATORS) ) {
00234             YAPET::Record<YAPET::PasswordRecord> record;
00235             YAPET::PasswordRecord *ptr_rec = record;
00236             strncpy ( (char*) ptr_rec->name, field_values[0].c_str(), YAPET::NAME_SIZE);
00237             strncpy ( (char*) ptr_rec->host, field_values[1].c_str(), YAPET::HOST_SIZE);
00238             strncpy ( (char*) ptr_rec->username, field_values[2].c_str(), YAPET::USERNAME_SIZE);
00239             strncpy ( (char*) ptr_rec->password, field_values[3].c_str(), YAPET::PASSWORD_SIZE);
00240             strncpy ( (char*) ptr_rec->comment, field_values[4].c_str(), YAPET::COMMENT_SIZE);
00241             list.push_back (YAPET::PartDec (record, key) );
00242 
00243             if (verbose) {
00244                 std::cout << ".";
00245                 std::cout.flush();
00246             }
00247         }
00248     }
00249 
00250     if (verbose) std::cout << std::endl;
00251 
00252     yapetfile.save (list);
00253     csvfile.close();
00254 }
00255 
00259 void
00260 CSVImport::printLog() const {
00261     if (logs.size() == 0) return;
00262 
00263     std::list<LogEntry>::const_iterator it = logs.begin();
00264 
00265     while (it != logs.end() ) {
00266         std::cout << "Line " << (*it).lineno << ": " << (*it).message << std::endl;
00267         it++;
00268     }
00269 }

Generated on Sun Sep 19 2010 15:37:13 for YAPET by  doxygen 1.7.1