20 #include "../config.h" 
   27 #include "ParserEventGeneratorKit.h" 
   51 #define LIBOFX_DEFAULT_INPUT_ENCODING "CP1252" 
   52 #define LIBOFX_DEFAULT_OUTPUT_ENCODING "UTF-8" 
   57 #ifdef MAKEFILE_DTD_PATH 
   68 #ifdef MAKEFILE_DTD_PATH 
   71   "/usr/local/share/libofx/dtd",
 
   72   "/usr/share/libofx/dtd",
 
   83   bool ofx_start = 
false;
 
   85   bool file_is_xml = 
false;
 
   86   bool used_iconv = 
false;
 
   87   std::ifstream input_file;
 
   88   std::ofstream tmp_file;
 
   90   char tmp_filename[256];
 
   93   iconv_t conversion_descriptor;
 
   97   if (p_filename != NULL && strcmp(p_filename, 
"") != 0)
 
   99     message_out(
DEBUG, std::string(
"ofx_proc_file():Opening file: ") + p_filename);
 
  101     input_file.open(p_filename);
 
  104       message_out(
ERROR, 
"ofx_proc_file():Unable to open the input file " + std::string(p_filename));
 
  107     mkTempFileName(
"libofxtmpXXXXXX", tmp_filename, 
sizeof(tmp_filename));
 
  109     message_out(
DEBUG, 
"ofx_proc_file(): Creating temp file: " + std::string(tmp_filename));
 
  111     tmp_file_fd = mkstemp_win32(tmp_filename);
 
  113     tmp_file_fd = mkstemp(tmp_filename);
 
  117       tmp_file.open(tmp_filename);
 
  120         message_out(
ERROR, 
"ofx_proc_file():Unable to open the created temp file " + std::string(tmp_filename));
 
  126       message_out(
ERROR, 
"ofx_proc_file():Unable to create a temp file at " + std::string(tmp_filename));
 
  130     if (input_file && tmp_file)
 
  132       std::size_t header_separator_idx;
 
  133       std::string header_name;
 
  134       std::string header_value;
 
  135       std::string ofx_encoding;
 
  136       std::string ofx_charset;
 
  139         std::stringbuf buffer;
 
  140         std::string s_buffer;
 
  141         input_file.get(buffer, 
'\n');
 
  143         s_buffer = buffer.str();
 
  147         if (!input_file.eof())
 
  150           if (input_file.fail()) 
 
  160           if (input_file.peek() == 
'\n')
 
  167         if (ofx_start == 
false && (s_buffer.find(
"<?xml") != std::string::npos))
 
  169           message_out(
DEBUG, 
"ofx_proc_file(): File is an actual XML file, iconv conversion will be skipped.");
 
  173         std::size_t ofx_start_idx;
 
  174         if (ofx_start == 
false)
 
  177             (libofx_context->currentFileType() == 
OFX &&
 
  178              ((ofx_start_idx = s_buffer.find(
"<OFX>")) != std::string::npos ||
 
  179               (ofx_start_idx = s_buffer.find(
"<ofx>")) != std::string::npos))
 
  181             (libofx_context->currentFileType() == 
OFC &&
 
  182              ((ofx_start_idx = s_buffer.find(
"<OFC>")) != std::string::npos ||
 
  183               (ofx_start_idx = s_buffer.find(
"<ofc>")) != std::string::npos))
 
  187             if (file_is_xml == 
false)
 
  189               s_buffer.erase(0, ofx_start_idx); 
 
  193             static char sp_charset_fixed[] = 
"SP_CHARSET_FIXED=1";
 
  194             if (putenv(sp_charset_fixed) != 0)
 
  198 #define OPENSP_UTF8_WARNING_TEXT "ofx_proc_file(): OpenSP cannot process an UTF-8 XML file without garbling it.  Furthermore, on windows the support for UTF-8 encode SGML files is broken. This is worked around by forcing a single byte encoding.  If the file is indeed UTF-8, it should pass through unmolested, but you will likely get 'non SGML character number' errors, even though the output is correct." 
  199             if (file_is_xml == 
true)
 
  210               static char sp_encoding[] = 
"SP_ENCODING=ms-dos";
 
  211               if (putenv(sp_encoding) != 0)
 
  218               static char sp_encoding[] = 
"SP_ENCODING=ms-dos"; 
 
  219               if (putenv(sp_encoding) != 0)
 
  224               std::string fromcode;
 
  226               if (ofx_encoding.compare(
"USASCII") == 0)
 
  228                 if (ofx_charset.compare(
"ISO-8859-1") == 0 || ofx_charset.compare(
"8859-1") == 0)
 
  231                   fromcode = 
"ISO-8859-1";
 
  233                 else if (ofx_charset.compare(
"1252") == 0 || ofx_charset.compare(
"CP1252") == 0)
 
  238                 else if (ofx_charset.compare(
"NONE") == 0)
 
  240                   fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
 
  244                   fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
 
  247               else if (ofx_encoding.compare(
"UTF-8") == 0 || ofx_encoding.compare(
"UNICODE") == 0)
 
  255                 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
 
  257               tocode = LIBOFX_DEFAULT_OUTPUT_ENCODING;
 
  258               message_out(
DEBUG, 
"ofx_proc_file(): Setting up iconv for fromcode: " + fromcode + 
", tocode: " + tocode);
 
  259               conversion_descriptor = iconv_open (tocode.c_str(), fromcode.c_str());
 
  267             if ((header_separator_idx = s_buffer.find(
':')) != std::string::npos)
 
  270               header_name.assign(s_buffer.substr(0, header_separator_idx));
 
  271               header_value.assign(s_buffer.substr(header_separator_idx + 1));
 
  272               while ( header_value[header_value.length() - 1 ] == 
'\n' ||
 
  273                       header_value[header_value.length() - 1 ] == 
'\r' )
 
  274                 header_value.erase(header_value.length() - 1);
 
  275               message_out(
DEBUG, 
"ofx_proc_file():Header: " + header_name + 
" with value: " + header_value + 
" has been found");
 
  276               if (header_name.compare(
"ENCODING") == 0)
 
  278                 ofx_encoding.assign(header_value);
 
  280               if (header_name.compare(
"CHARSET") == 0)
 
  282                 ofx_charset.assign(header_value);
 
  288         if (file_is_xml == 
true || (ofx_start == 
true && ofx_end == 
false))
 
  290           if (ofx_start == 
true)
 
  297             if (s_buffer.empty())
 
  301           if (file_is_xml == 
false)
 
  304             size_t inbytesleft = s_buffer.size();
 
  305             size_t outbytesleft = inbytesleft * 2 - 1;
 
  306             char * iconv_buffer = (
char*) malloc (inbytesleft * 2);
 
  307             memset(iconv_buffer, 0, inbytesleft * 2);
 
  308             const char* inchar = s_buffer.c_str();
 
  309             char * outchar = iconv_buffer;
 
  310             int iconv_retval = iconv (conversion_descriptor,
 
  311 #ifdef HAVE_ICONV_CONST
 
  314                                       const_cast<char**
>(&inchar),
 
  316                                       &inbytesleft, &outchar, &outbytesleft);
 
  317             if (iconv_retval == -1)
 
  323             s_buffer = std::string(iconv_buffer, outchar - iconv_buffer);
 
  328           tmp_file << s_buffer << std::endl;
 
  331         if (ofx_start == 
true &&
 
  333               (libofx_context->currentFileType() == 
OFX &&
 
  334                ((ofx_start_idx = s_buffer.find(
"</OFX>")) != std::string::npos ||
 
  335                 (ofx_start_idx = s_buffer.find(
"</ofx>")) != std::string::npos))
 
  336               || (libofx_context->currentFileType() == 
OFC &&
 
  337                   ((ofx_start_idx = s_buffer.find(
"</OFC>")) != std::string::npos ||
 
  338                    (ofx_start_idx = s_buffer.find(
"</ofc>")) != std::string::npos))
 
  347       while (!input_file.eof() && !input_file.bad());
 
  352     if (used_iconv == 
true)
 
  354       iconv_close(conversion_descriptor);
 
  357     char filename_openspdtd[255];
 
  358     char filename_dtd[255];
 
  359     char filename_ofx[255];
 
  361     if (libofx_context->currentFileType() == 
OFX)
 
  365     else if (libofx_context->currentFileType() == 
OFC)
 
  371       message_out(
ERROR, std::string(
"ofx_proc_file(): Error unknown file format for the OFX parser"));
 
  374     if ((std::string)filename_dtd != 
"" && (std::string)filename_openspdtd != 
"")
 
  376       strncpy(filename_ofx, tmp_filename, 255); 
 
  377       filenames[0] = filename_openspdtd;
 
  378       filenames[1] = filename_dtd;
 
  379       filenames[2] = filename_ofx;
 
  381       if (libofx_context->currentFileType() == 
OFX)
 
  385       else if (libofx_context->currentFileType() == 
OFC)
 
  391         message_out(
ERROR, std::string(
"ofx_proc_file(): Error unknown file format for the OFX parser"));
 
  394       if (remove(tmp_filename) != 0)
 
  396         message_out(
ERROR, 
"ofx_proc_file(): Error deleting temporary file " + std::string(tmp_filename));
 
  419 static std::string find_tag_open (std::string& input_string, 
size_t& pos_start, 
size_t& pos_end)
 
  421   pos_start = input_string.find (
'<', pos_start);
 
  423   if (pos_start == std::string::npos)
 
  425     pos_end = std::string::npos;
 
  426     return std::string();
 
  429   pos_end = input_string.find (
'>', pos_start + 1);
 
  430   if (pos_end != std::string::npos)
 
  431     pos_end = pos_end + 1;
 
  432   size_t tag_size = (pos_end - 1) - (pos_start + 1);
 
  433   return input_string.substr(pos_start + 1, tag_size);
 
  441 static void find_tag_close (std::string& input_string, std::string& tag_name, 
size_t& pos)
 
  443   size_t start_idx = input_string.find (
"</" + tag_name + 
">", pos);
 
  445   if (start_idx == std::string::npos)
 
  449     std::string new_tag_name = find_tag_open (input_string, start_idx, end_idx);
 
  450     if (!new_tag_name.empty())
 
  452       message_out(
DEBUG, 
"find_tag_close() fell back to next open tag: " + new_tag_name);
 
  460       pos = input_string.length();
 
  465     pos = start_idx + tag_name.length() + 3;
 
  484   size_t last_known_good_pos = 0;
 
  485   size_t open_tag_start_pos = last_known_good_pos;
 
  486   size_t open_tag_end_pos;
 
  487   size_t close_tag_end_pos;
 
  489   std::string tag_name = find_tag_open(input_string, open_tag_start_pos, open_tag_end_pos);
 
  490   while (!tag_name.empty())
 
  493     if ((tag_name.find(
'.') != std::string::npos) ||   
 
  494         (tag_name == 
"CATEGORY"))                  
 
  496       close_tag_end_pos = open_tag_end_pos;
 
  497       find_tag_close (input_string, tag_name, close_tag_end_pos);
 
  498       size_t tag_size = close_tag_end_pos - open_tag_start_pos;
 
  499       std::string prop_tag = input_string.substr(open_tag_start_pos, tag_size);
 
  501       input_string.erase(open_tag_start_pos, tag_size);
 
  502       last_known_good_pos = open_tag_start_pos;
 
  506       last_known_good_pos = open_tag_end_pos;
 
  509     open_tag_start_pos = last_known_good_pos;
 
  510     if (last_known_good_pos != std::string::npos)
 
  511       tag_name = find_tag_open(input_string, open_tag_start_pos, open_tag_end_pos);
 
  518 static std::string get_dtd_installation_directory()
 
  522   char ch_fn[MAX_PATH], *p;
 
  525   if (!GetModuleFileName(NULL, ch_fn, MAX_PATH)) 
return "";
 
  527   if ((p = strrchr(ch_fn, 
'\\')) != NULL)
 
  530   p = strrchr(ch_fn, 
'\\');
 
  531   if (p && (_stricmp(p + 1, 
"bin") == 0 ||
 
  532             _stricmp(p + 1, 
"lib") == 0))
 
  536   str_fn += 
"\\share\\libofx\\dtd";
 
  556 std::string 
find_dtd(LibofxContextPtr ctx, 
const std::string& dtd_filename)
 
  558   std::string dtd_path_filename;
 
  561   dtd_path_filename = 
reinterpret_cast<const LibofxContext*
>(ctx)->dtdDir();
 
  562   if (!dtd_path_filename.empty())
 
  564     dtd_path_filename.append(dtd_filename);
 
  565     std::ifstream dtd_file(dtd_path_filename.c_str());
 
  569       return dtd_path_filename;
 
  574   dtd_path_filename = get_dtd_installation_directory();
 
  575   if (!dtd_path_filename.empty())
 
  577     dtd_path_filename.append(DIRSEP);
 
  578     dtd_path_filename.append(dtd_filename);
 
  579     std::ifstream dtd_file(dtd_path_filename.c_str());
 
  583       return dtd_path_filename;
 
  588   env_dtd_path = getenv(
"OFX_DTD_PATH");
 
  591     dtd_path_filename = env_dtd_path;
 
  592     dtd_path_filename.append(DIRSEP);
 
  593     dtd_path_filename.append(dtd_filename);
 
  594     std::ifstream dtd_file(dtd_path_filename.c_str());
 
  597       message_out(
STATUS, 
"find_dtd():OFX_DTD_PATH env variable was was present, but unable to open the file " + dtd_path_filename);
 
  602       return dtd_path_filename;
 
  609     dtd_path_filename.append(DIRSEP);
 
  610     dtd_path_filename.append(dtd_filename);
 
  611     std::ifstream dtd_file(dtd_path_filename.c_str());
 
  614       message_out(
DEBUG, 
"find_dtd():Unable to open the file " + dtd_path_filename);
 
  619       return dtd_path_filename;
 
  624   dtd_path_filename = 
"";
 
  625   dtd_path_filename.append(
"..");
 
  626   dtd_path_filename.append(DIRSEP);
 
  627   dtd_path_filename.append(
"dtd");
 
  628   dtd_path_filename.append(DIRSEP);
 
  629   dtd_path_filename.append(dtd_filename);
 
  630   std::ifstream dtd_file(dtd_path_filename.c_str());
 
  633     message_out(
DEBUG, 
"find_dtd(): Unable to open the file " + dtd_path_filename + 
", most likely we are not in the source tree.");
 
  638     return dtd_path_filename;
 
  642   message_out(
ERROR, 
"find_dtd():Unable to find the DTD named " + dtd_filename);