20 #include "../config.h" 27 #include "ParserEventGeneratorKit.h" 51 #define LIBOFX_DEFAULT_INPUT_ENCODING "CP1252" 52 #define LIBOFX_DEFAULT_OUTPUT_ENCODING "UTF-8" 58 #ifdef MAKEFILE_DTD_PATH 69 #ifdef MAKEFILE_DTD_PATH 72 "/usr/local/share/libofx/dtd",
73 "/usr/share/libofx/dtd",
84 bool ofx_start =
false;
86 bool file_is_xml =
false;
87 bool used_iconv =
false;
91 char tmp_filename[256];
94 iconv_t conversion_descriptor;
98 if (p_filename != NULL && strcmp(p_filename,
"") != 0)
102 input_file.open(p_filename);
105 message_out(
ERROR,
"ofx_proc_file():Unable to open the input file " +
string(p_filename));
108 mkTempFileName(
"libofxtmpXXXXXX", tmp_filename,
sizeof(tmp_filename));
110 message_out(
DEBUG,
"ofx_proc_file(): Creating temp file: " +
string(tmp_filename));
112 tmp_file_fd = mkstemp_win32(tmp_filename);
114 tmp_file_fd = mkstemp(tmp_filename);
118 tmp_file.open(tmp_filename);
121 message_out(
ERROR,
"ofx_proc_file():Unable to open the created temp file " +
string(tmp_filename));
127 message_out(
ERROR,
"ofx_proc_file():Unable to create a temp file at " +
string(tmp_filename));
131 if (input_file && tmp_file)
133 std::size_t header_separator_idx;
142 input_file.get(buffer,
'\n');
144 s_buffer = buffer.str();
148 if (!input_file.eof())
151 if (input_file.fail())
161 if (input_file.peek() ==
'\n')
168 if (ofx_start ==
false && (s_buffer.find(
"<?xml") != string::npos))
170 message_out(
DEBUG,
"ofx_proc_file(): File is an actual XML file, iconv conversion will be skipped.");
174 std::size_t ofx_start_idx;
175 if (ofx_start ==
false)
178 (libofx_context->currentFileType() ==
OFX &&
179 ((ofx_start_idx = s_buffer.find(
"<OFX>")) != string::npos ||
180 (ofx_start_idx = s_buffer.find(
"<ofx>")) != string::npos))
182 (libofx_context->currentFileType() ==
OFC &&
183 ((ofx_start_idx = s_buffer.find(
"<OFC>")) != string::npos ||
184 (ofx_start_idx = s_buffer.find(
"<ofc>")) != string::npos))
188 if (file_is_xml ==
false)
190 s_buffer.erase(0, ofx_start_idx);
194 if (file_is_xml ==
true)
196 static char sp_charset_fixed[] =
"SP_CHARSET_FIXED=1";
197 if (putenv(sp_charset_fixed) != 0)
208 static char sp_encoding[] =
"SP_ENCODING=ms-dos";
209 if (putenv(sp_encoding) != 0)
216 static char sp_charset_fixed[] =
"SP_CHARSET_FIXED=1";
217 if (putenv(sp_charset_fixed) != 0)
221 static char sp_encoding[] =
"SP_ENCODING=ms-dos";
222 if (putenv(sp_encoding) != 0)
229 if (ofx_encoding.compare(
"USASCII") == 0)
231 if (ofx_charset.compare(
"ISO-8859-1") == 0 || ofx_charset.compare(
"8859-1") == 0)
234 fromcode =
"ISO-8859-1";
236 else if (ofx_charset.compare(
"1252") == 0 || ofx_charset.compare(
"CP1252") == 0)
241 else if (ofx_charset.compare(
"NONE") == 0)
243 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
247 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
250 else if (ofx_encoding.compare(
"UTF-8") == 0 || ofx_encoding.compare(
"UNICODE") == 0)
257 fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
259 tocode = LIBOFX_DEFAULT_OUTPUT_ENCODING;
260 message_out(
DEBUG,
"ofx_proc_file(): Setting up iconv for fromcode: " + fromcode +
", tocode: " + tocode);
261 conversion_descriptor = iconv_open (tocode.c_str(), fromcode.c_str());
269 if ((header_separator_idx = s_buffer.find(
':')) != string::npos)
272 header_name.assign(s_buffer.substr(0, header_separator_idx));
273 header_value.assign(s_buffer.substr(header_separator_idx + 1));
274 while ( header_value[header_value.length() - 1 ] ==
'\n' ||
275 header_value[header_value.length() - 1 ] ==
'\r' )
276 header_value.erase(header_value.length() - 1);
277 message_out(
DEBUG,
"ofx_proc_file():Header: " + header_name +
" with value: " + header_value +
" has been found");
278 if (header_name.compare(
"ENCODING") == 0)
280 ofx_encoding.assign(header_value);
282 if (header_name.compare(
"CHARSET") == 0)
284 ofx_charset.assign(header_value);
290 if (file_is_xml ==
true || (ofx_start ==
true && ofx_end ==
false))
292 if (ofx_start ==
true)
299 if (s_buffer.empty())
303 if (file_is_xml ==
false)
306 size_t inbytesleft = s_buffer.size();
307 size_t outbytesleft = inbytesleft * 2 - 1;
308 char * iconv_buffer = (
char*) malloc (inbytesleft * 2);
309 memset(iconv_buffer, 0, inbytesleft * 2);
310 #if defined(__WIN32__) || defined(__sun) || defined(__NetBSD__) 311 const char * inchar = (
const char *)s_buffer.c_str();
313 char * inchar = (
char *)s_buffer.c_str();
315 char * outchar = iconv_buffer;
316 int iconv_retval = iconv (conversion_descriptor,
317 &inchar, &inbytesleft,
318 &outchar, &outbytesleft);
319 if (iconv_retval == -1)
325 s_buffer = std::string(iconv_buffer, outchar - iconv_buffer);
330 tmp_file << s_buffer << endl;
333 if (ofx_start ==
true &&
335 (libofx_context->currentFileType() ==
OFX &&
336 ((ofx_start_idx = s_buffer.find(
"</OFX>")) != string::npos ||
337 (ofx_start_idx = s_buffer.find(
"</ofx>")) != string::npos))
338 || (libofx_context->currentFileType() ==
OFC &&
339 ((ofx_start_idx = s_buffer.find(
"</OFC>")) != string::npos ||
340 (ofx_start_idx = s_buffer.find(
"</ofc>")) != string::npos))
349 while (!input_file.eof() && !input_file.bad());
354 if (used_iconv ==
true)
356 iconv_close(conversion_descriptor);
359 char filename_openspdtd[255];
360 char filename_dtd[255];
361 char filename_ofx[255];
362 strncpy(filename_openspdtd,
find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255);
363 if (libofx_context->currentFileType() ==
OFX)
365 strncpy(filename_dtd,
find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255);
367 else if (libofx_context->currentFileType() ==
OFC)
369 strncpy(filename_dtd,
find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255);
373 message_out(
ERROR,
string(
"ofx_proc_file(): Error unknown file format for the OFX parser"));
376 if ((
string)filename_dtd !=
"" && (
string)filename_openspdtd !=
"")
378 strncpy(filename_ofx, tmp_filename, 255);
379 filenames[0] = filename_openspdtd;
380 filenames[1] = filename_dtd;
381 filenames[2] = filename_ofx;
382 if (libofx_context->currentFileType() ==
OFX)
386 else if (libofx_context->currentFileType() ==
OFC)
392 message_out(
ERROR,
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 " +
string(tmp_filename));
416 static string find_tag_open (
string& input_string,
size_t& pos_start,
size_t& pos_end)
418 pos_start = input_string.find (
'<', pos_start);
420 if (pos_start == string::npos)
422 pos_end = string::npos;
426 pos_end = input_string.find (
'>', pos_start + 1);
427 if (pos_end != string::npos)
428 pos_end = pos_end + 1;
429 size_t tag_size = (pos_end - 1) - (pos_start + 1);
430 return input_string.substr(pos_start + 1, tag_size);
438 static void find_tag_close (
string& input_string,
string& tag_name,
size_t& pos)
440 size_t start_idx = input_string.find (
"</" + tag_name +
">", pos);
442 if (start_idx == string::npos)
446 string new_tag_name = find_tag_open (input_string, start_idx, end_idx);
447 if (!new_tag_name.empty())
449 message_out(
DEBUG,
"find_tag_close() fell back to next open tag: " + new_tag_name);
457 pos = input_string.length();
462 pos = start_idx + tag_name.length() + 3;
481 size_t last_known_good_pos = 0;
482 size_t open_tag_start_pos = last_known_good_pos;
483 size_t open_tag_end_pos;
484 size_t close_tag_end_pos;
486 string tag_name = find_tag_open(input_string, open_tag_start_pos, open_tag_end_pos);
487 while (!tag_name.empty())
490 if ((tag_name.find(
'.') != string::npos) ||
491 (tag_name ==
"CATEGORY"))
493 close_tag_end_pos = open_tag_end_pos;
494 find_tag_close (input_string, tag_name, close_tag_end_pos);
495 size_t tag_size = close_tag_end_pos - open_tag_start_pos;
496 string prop_tag = input_string.substr(open_tag_start_pos, tag_size);
498 input_string.erase(open_tag_start_pos, tag_size);
499 last_known_good_pos = open_tag_start_pos;
503 last_known_good_pos = open_tag_end_pos;
506 open_tag_start_pos = last_known_good_pos;
507 if (last_known_good_pos != string::npos)
508 tag_name = find_tag_open(input_string, open_tag_start_pos, open_tag_end_pos);
515 static std::string get_dtd_installation_directory()
519 char ch_fn[MAX_PATH], *p;
522 if (!GetModuleFileName(NULL, ch_fn, MAX_PATH))
return "";
524 if ((p = strrchr(ch_fn,
'\\')) != NULL)
527 p = strrchr(ch_fn,
'\\');
528 if (p && (_stricmp(p + 1,
"bin") == 0 ||
529 _stricmp(p + 1,
"lib") == 0))
533 str_fn +=
"\\share\\libofx\\dtd";
552 std::string
find_dtd(LibofxContextPtr ctx,
const std::string& dtd_filename)
554 string dtd_path_filename;
557 dtd_path_filename =
reinterpret_cast<const LibofxContext*
>(ctx)->dtdDir();
558 if (!dtd_path_filename.empty())
560 dtd_path_filename.append(dtd_filename);
561 ifstream dtd_file(dtd_path_filename.c_str());
565 return dtd_path_filename;
570 dtd_path_filename = get_dtd_installation_directory();
571 if (!dtd_path_filename.empty())
573 dtd_path_filename.append(DIRSEP);
574 dtd_path_filename.append(dtd_filename);
575 ifstream dtd_file(dtd_path_filename.c_str());
579 return dtd_path_filename;
584 env_dtd_path = getenv(
"OFX_DTD_PATH");
587 dtd_path_filename.append(env_dtd_path);
588 dtd_path_filename.append(DIRSEP);
589 dtd_path_filename.append(dtd_filename);
590 ifstream dtd_file(dtd_path_filename.c_str());
593 message_out(
STATUS,
"find_dtd():OFX_DTD_PATH env variable was was present, but unable to open the file " + dtd_path_filename);
598 return dtd_path_filename;
605 dtd_path_filename.append(DIRSEP);
606 dtd_path_filename.append(dtd_filename);
607 ifstream dtd_file(dtd_path_filename.c_str());
610 message_out(
DEBUG,
"find_dtd():Unable to open the file " + dtd_path_filename);
615 return dtd_path_filename;
620 dtd_path_filename =
"";
621 dtd_path_filename.append(
"..");
622 dtd_path_filename.append(DIRSEP);
623 dtd_path_filename.append(
"dtd");
624 dtd_path_filename.append(DIRSEP);
625 dtd_path_filename.append(dtd_filename);
626 ifstream dtd_file(dtd_path_filename.c_str());
629 message_out(
DEBUG,
"find_dtd(): Unable to open the file " + dtd_path_filename +
", most likely we are not in the source tree.");
634 return dtd_path_filename;
638 message_out(
ERROR,
"find_dtd():Unable to find the DTD named " + dtd_filename);
string sanitize_proprietary_tags(string input_string)
Removes proprietary tags and comments.
Various simple functions for type conversion & al.
int ofc_proc_sgml(LibofxContext *libofx_context, int argc, char *const *argv)
Parses a DTD and OFX file(s)
int message_out(OfxMsgType error_type, const string message)
Message output function.
Preprocessing of the OFX files before parsing.
OFX/SGML parsing functionnality.
const int DTD_SEARCH_PATH_NUM
The number of different paths to search for DTDs.
std::string find_dtd(LibofxContextPtr ctx, const std::string &dtd_filename)
Find the appropriate DTD for the file version.
Message IO functionality.
OFX/SGML parsing functionnality.
const char * DTD_SEARCH_PATH[DTD_SEARCH_PATH_NUM]
The list of paths to search for the DTDs.
int ofx_proc_sgml(LibofxContext *libofx_context, int argc, char *const *argv)
Parses a DTD and OFX file(s)
int ofx_proc_file(LibofxContextPtr ctx, const char *p_filename)
File pre-processing of OFX AND for OFC files.