20 #include "../config.h"
26 #include "ParserEventGeneratorKit.h"
50 #define LIBOFX_DEFAULT_INPUT_ENCODING "CP1252"
51 #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",
75 const unsigned int READ_BUFFER_SIZE = 1024;
84 bool ofx_start =
false;
86 bool file_is_xml =
false;
90 char buffer[READ_BUFFER_SIZE];
94 char tmp_filename[256];
97 iconv_t conversion_descriptor;
101 if (p_filename != NULL && strcmp(p_filename,
"") != 0)
105 input_file.open(p_filename);
108 message_out(
ERROR,
"ofx_proc_file():Unable to open the input file " +
string(p_filename));
111 mkTempFileName(
"libofxtmpXXXXXX", tmp_filename,
sizeof(tmp_filename));
113 message_out(
DEBUG,
"ofx_proc_file(): Creating temp file: " +
string(tmp_filename));
114 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 " +
string(tmp_filename));
126 message_out(
ERROR,
"ofx_proc_file():Unable to create a temp file at " +
string(tmp_filename));
130 if (input_file && tmp_file)
132 int header_separator_idx;
140 bool end_of_line =
false;
143 input_file.get(buffer,
sizeof(buffer),
'\n');
145 s_buffer.append(buffer);
149 if (input_file.eof())
153 if (input_file.fail())
163 if (input_file.peek() ==
'\n')
168 s_buffer.append(
"\n");
174 while (!input_file.eof() && !end_of_line);
176 if (ofx_start ==
false && (s_buffer.find(
"<?xml") != string::npos))
178 message_out(
DEBUG,
"ofx_proc_file(): File is an actual XML file, iconv conversion will be skipped.");
183 if (ofx_start ==
false &&
185 (libofx_context->currentFileType() ==
OFX &&
186 ((ofx_start_idx = s_buffer.find(
"<OFX>")) !=
187 string::npos || (ofx_start_idx = s_buffer.find(
"<ofx>")) != string::npos))
188 || (libofx_context->currentFileType() ==
OFC &&
189 ((ofx_start_idx = s_buffer.find(
"<OFC>")) != string::npos ||
190 (ofx_start_idx = s_buffer.find(
"<ofc>")) != string::npos))
195 if (file_is_xml ==
false)
197 s_buffer.erase(0, ofx_start_idx);
201 if (file_is_xml ==
true)
203 static char sp_charset_fixed[] =
"SP_CHARSET_FIXED=1";
204 if (putenv(sp_charset_fixed) != 0)
215 static char sp_encoding[] =
"SP_ENCODING=ms-dos";
216 if (putenv(sp_encoding) != 0)
223 static char sp_charset_fixed[] =
"SP_CHARSET_FIXED=1";
224 if (putenv(sp_charset_fixed) != 0)
228 static char sp_encoding[] =
"SP_ENCODING=ms-dos";
229 if (putenv(sp_encoding) != 0)
236 if (ofx_encoding.compare(
"USASCII") == 0)
238 if (ofx_charset.compare(
"ISO-8859-1") == 0 || ofx_charset.compare(
"8859-1") == 0)
241 fromcode =
"ISO-8859-1";
243 else if (ofx_charset.compare(
"1252") == 0 || ofx_charset.compare(
"CP1252") == 0)
248 else if (ofx_charset.compare(
"NONE") == 0)
250 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
254 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
257 else if (ofx_encoding.compare(
"UTF-8") == 0 || ofx_encoding.compare(
"UNICODE") == 0)
264 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
266 tocode = LIBOFX_DEFAULT_OUTPUT_ENCODING;
267 message_out(
DEBUG,
"ofx_proc_file(): Setting up iconv for fromcode: " + fromcode +
", tocode: " + tocode);
268 conversion_descriptor = iconv_open (tocode.c_str(), fromcode.c_str());
275 if ((header_separator_idx = s_buffer.find(
':')) != string::npos)
278 header_name.assign(s_buffer.substr(0, header_separator_idx));
279 header_value.assign(s_buffer.substr(header_separator_idx + 1));
280 while ( header_value[header_value.length() -1 ] ==
'\n' ||
281 header_value[header_value.length() -1 ] ==
'\r' )
282 header_value.erase(header_value.length() - 1);
283 message_out(
DEBUG,
"ofx_proc_file():Header: " + header_name +
" with value: " + header_value +
" has been found");
284 if (header_name.compare(
"ENCODING") == 0)
286 ofx_encoding.assign(header_value);
288 if (header_name.compare(
"CHARSET") == 0)
290 ofx_charset.assign(header_value);
295 if (file_is_xml ==
true || (ofx_start ==
true && ofx_end ==
false))
297 if (ofx_start ==
true)
306 if (file_is_xml ==
false)
309 size_t inbytesleft = strlen(s_buffer.c_str());
310 size_t outbytesleft = inbytesleft * 2 - 1;
311 iconv_buffer = (
char*) malloc (inbytesleft * 2);
312 memset(iconv_buffer, 0, inbytesleft * 2);
313 #if defined(OS_WIN32) || defined(__sun) || defined(__NetBSD__)
314 const char * inchar = (
const char *)s_buffer.c_str();
316 char * inchar = (
char *)s_buffer.c_str();
318 char * outchar = iconv_buffer;
319 int iconv_retval = iconv (conversion_descriptor,
320 &inchar, &inbytesleft,
321 &outchar, &outbytesleft);
322 if (iconv_retval == -1)
326 s_buffer = iconv_buffer;
331 tmp_file.write(s_buffer.c_str(), s_buffer.length());
334 if (ofx_start ==
true &&
336 (libofx_context->currentFileType() ==
OFX &&
337 ((ofx_start_idx = s_buffer.find(
"</OFX>")) != string::npos ||
338 (ofx_start_idx = s_buffer.find(
"</ofx>")) != string::npos))
339 || (libofx_context->currentFileType() ==
OFC &&
340 ((ofx_start_idx = s_buffer.find(
"</OFC>")) != string::npos ||
341 (ofx_start_idx = s_buffer.find(
"</ofc>")) != string::npos))
350 while (!input_file.eof() && !input_file.bad());
355 if (file_is_xml ==
false)
357 iconv_close(conversion_descriptor);
360 char filename_openspdtd[255];
361 char filename_dtd[255];
362 char filename_ofx[255];
363 strncpy(filename_openspdtd,
find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255);
364 if (libofx_context->currentFileType() ==
OFX)
366 strncpy(filename_dtd,
find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255);
368 else if (libofx_context->currentFileType() ==
OFC)
370 strncpy(filename_dtd,
find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255);
374 message_out(
ERROR,
string(
"ofx_proc_file(): Error unknown file format for the OFX parser"));
377 if ((
string)filename_dtd !=
"" && (
string)filename_openspdtd !=
"")
379 strncpy(filename_ofx, tmp_filename, 255);
380 filenames[0] = filename_openspdtd;
381 filenames[1] = filename_dtd;
382 filenames[2] = filename_ofx;
383 if (libofx_context->currentFileType() ==
OFX)
387 else if (libofx_context->currentFileType() ==
OFC)
393 message_out(
ERROR,
string(
"ofx_proc_file(): Error unknown file format for the OFX parser"));
395 if (
remove(tmp_filename) != 0)
397 message_out(
ERROR,
"ofx_proc_file(): Error deleting temporary file " +
string(tmp_filename));
421 bool tag_open =
false;
422 int tag_open_idx = 0;
423 bool closing_tag_open =
false;
424 int orig_tag_open_idx = 0;
425 bool proprietary_tag =
false;
426 bool proprietary_closing_tag =
false;
427 int crop_end_idx = 0;
428 char buffer[READ_BUFFER_SIZE] =
"";
429 char tagname[READ_BUFFER_SIZE] =
"";
431 char close_tagname[READ_BUFFER_SIZE] =
"";
433 for (i = 0; i < READ_BUFFER_SIZE; i++)
437 close_tagname[i] = 0;
440 size_t input_string_size = input_string.size();
450 for (i = 0; i < std::min(input_string_size,
size_t(READ_BUFFER_SIZE)); i++)
452 if (input_string.c_str()[i] ==
'<')
456 if (proprietary_tag ==
true && input_string.c_str()[i+1] ==
'/')
459 closing_tag_open =
true;
461 if (strncmp(tagname, &(input_string.c_str()[i+2]), strlen(tagname)) != 0)
465 crop_end_idx = i - 1;
471 proprietary_closing_tag =
true;
474 else if (proprietary_tag ==
true)
477 crop_end_idx = i - 1;
481 else if (input_string.c_str()[i] ==
'>')
484 closing_tag_open =
false;
485 tagname[tagname_idx] = 0;
487 if (proprietary_closing_tag ==
true)
493 else if (tag_open ==
true && closing_tag_open ==
false)
495 if (input_string.c_str()[i] ==
'.')
497 if (proprietary_tag !=
true)
499 orig_tag_open_idx = tag_open_idx;
500 proprietary_tag =
true;
503 tagname[tagname_idx] = input_string.c_str()[i];
507 if (strip ==
true && orig_tag_open_idx < input_string.size())
509 input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
510 message_out(
INFO,
"sanitize_proprietary_tags() (end tag or new tag) removed: " +
string(buffer));
511 input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
512 i = orig_tag_open_idx - 1;
513 proprietary_tag =
false;
514 proprietary_closing_tag =
false;
515 closing_tag_open =
false;
519 input_string_size = input_string.size();
523 if (proprietary_tag ==
true && orig_tag_open_idx < input_string.size())
525 if (crop_end_idx == 0)
527 crop_end_idx = input_string.size() - 1;
529 input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
530 message_out(
INFO,
"sanitize_proprietary_tags() (end of line) removed: " +
string(buffer));
531 input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
532 input_string_size = input_string.size();
539 static std::string get_dtd_installation_directory()
543 char ch_fn[MAX_PATH], *p;
546 if (!GetModuleFileName(NULL, ch_fn, MAX_PATH))
return "";
548 if ((p = strrchr(ch_fn,
'\\')) != NULL)
551 p = strrchr(ch_fn,
'\\');
552 if (p && (_stricmp(p + 1,
"bin") == 0 ||
553 _stricmp(p + 1,
"lib") == 0))
557 str_fn +=
"\\share\\libofx\\dtd";
576 std::string
find_dtd(LibofxContextPtr ctx,
const std::string& dtd_filename)
578 string dtd_path_filename;
581 dtd_path_filename =
reinterpret_cast<const LibofxContext*
>(ctx)->dtdDir();
582 if (!dtd_path_filename.empty())
584 dtd_path_filename.append(dtd_filename);
585 ifstream dtd_file(dtd_path_filename.c_str());
589 return dtd_path_filename;
594 dtd_path_filename = get_dtd_installation_directory();
595 if (!dtd_path_filename.empty())
597 dtd_path_filename.append(DIRSEP);
598 dtd_path_filename.append(dtd_filename);
599 ifstream dtd_file(dtd_path_filename.c_str());
603 return dtd_path_filename;
608 env_dtd_path = getenv(
"OFX_DTD_PATH");
611 dtd_path_filename.append(env_dtd_path);
612 dtd_path_filename.append(DIRSEP);
613 dtd_path_filename.append(dtd_filename);
614 ifstream dtd_file(dtd_path_filename.c_str());
617 message_out(
STATUS,
"find_dtd():OFX_DTD_PATH env variable was was present, but unable to open the file " + dtd_path_filename);
622 return dtd_path_filename;
629 dtd_path_filename.append(DIRSEP);
630 dtd_path_filename.append(dtd_filename);
631 ifstream dtd_file(dtd_path_filename.c_str());
634 message_out(
DEBUG,
"find_dtd():Unable to open the file " + dtd_path_filename);
639 return dtd_path_filename;
644 dtd_path_filename =
"";
645 dtd_path_filename.append(
"..");
646 dtd_path_filename.append(DIRSEP);
647 dtd_path_filename.append(
"dtd");
648 dtd_path_filename.append(DIRSEP);
649 dtd_path_filename.append(dtd_filename);
650 ifstream dtd_file(dtd_path_filename.c_str());
653 message_out(
DEBUG,
"find_dtd(): Unable to open the file " + dtd_path_filename +
", most likely we are not in the source tree.");
658 return dtd_path_filename;
662 message_out(
ERROR,
"find_dtd():Unable to find the DTD named " + dtd_filename);
int ofx_proc_file(LibofxContextPtr ctx, const char *p_filename)
File pre-processing of OFX AND for OFC files.
const int DTD_SEARCH_PATH_NUM
The number of different paths to search for DTDs.
int message_out(OfxMsgType error_type, const string message)
Message output function.
OFX/SGML parsing functionnality.
const char * DTD_SEARCH_PATH[DTD_SEARCH_PATH_NUM]
The list of paths to search for the DTDs.
int ofc_proc_sgml(LibofxContext *libofx_context, int argc, char *const *argv)
Parses a DTD and OFX file(s)
Various simple functions for type conversion & al.
int ofx_proc_sgml(LibofxContext *libofx_context, int argc, char *const *argv)
Parses a DTD and OFX file(s)
string sanitize_proprietary_tags(string input_string)
Removes proprietary tags and comments.
OFX/SGML parsing functionnality.
Message IO functionality.
Preprocessing of the OFX files before parsing.
std::string find_dtd(LibofxContextPtr ctx, const std::string &dtd_filename)
Find the appropriate DTD for the file version.