LibOFX
ofx_preproc.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002           ofx_preproc.cpp
00003                              -------------------
00004     copyright            : (C) 2002 by Benoit Gr�oir
00005     email                : benoitg@coeus.ca
00006 ***************************************************************************/
00012 /***************************************************************************
00013  *                                                                         *
00014  *   This program is free software; you can redistribute it and/or modify  *
00015  *   it under the terms of the GNU General Public License as published by  *
00016  *   the Free Software Foundation; either version 2 of the License, or     *
00017  *   (at your option) any later version.                                   *
00018  *                                                                         *
00019  ***************************************************************************/
00020 #include "../config.h"
00021 #include <iostream>
00022 #include <fstream>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string>
00026 #include "ParserEventGeneratorKit.h"
00027 #include "libofx.h"
00028 #include "messages.hh"
00029 #include "ofx_sgml.hh"
00030 #include "ofc_sgml.hh"
00031 #include "ofx_preproc.hh"
00032 #include "ofx_utilities.hh"
00033 #ifdef HAVE_ICONV
00034 #include <iconv.h>
00035 #endif
00036 
00037 #ifdef OS_WIN32
00038 # define DIRSEP "\\"
00039 #else
00040 # define DIRSEP "/"
00041 #endif
00042 
00043 #ifdef OS_WIN32
00044 # include "win32.hh"
00045 # include <windows.h> // for GetModuleFileName()
00046 # undef ERROR
00047 # undef DELETE
00048 #endif
00049 
00050 #define LIBOFX_DEFAULT_INPUT_ENCODING "CP1252"
00051 #define LIBOFX_DEFAULT_OUTPUT_ENCODING "UTF-8"
00052 
00053 using namespace std;
00057 #ifdef MAKEFILE_DTD_PATH
00058 const int DTD_SEARCH_PATH_NUM = 4;
00059 #else
00060 const int DTD_SEARCH_PATH_NUM = 3;
00061 #endif
00062 
00066 const char *DTD_SEARCH_PATH[DTD_SEARCH_PATH_NUM] =
00067 {
00068 #ifdef MAKEFILE_DTD_PATH
00069   MAKEFILE_DTD_PATH ,
00070 #endif
00071   "/usr/local/share/libofx/dtd",
00072   "/usr/share/libofx/dtd",
00073   "~"
00074 };
00075 const unsigned int READ_BUFFER_SIZE = 1024;
00076 
00081 int ofx_proc_file(LibofxContextPtr ctx, const char * p_filename)
00082 {
00083   LibofxContext *libofx_context;
00084   bool ofx_start = false;
00085   bool ofx_end = false;
00086 
00087   ifstream input_file;
00088   ofstream tmp_file;
00089   char buffer[READ_BUFFER_SIZE];
00090   char iconv_buffer[READ_BUFFER_SIZE * 2];
00091   string s_buffer;
00092   char *filenames[3];
00093   char tmp_filename[256];
00094   int tmp_file_fd;
00095 #ifdef HAVE_ICONV
00096   iconv_t conversion_descriptor;
00097 #endif
00098   libofx_context = (LibofxContext*)ctx;
00099 
00100   if (p_filename != NULL && strcmp(p_filename, "") != 0)
00101   {
00102     message_out(DEBUG, string("ofx_proc_file():Opening file: ") + p_filename);
00103 
00104     input_file.open(p_filename);
00105     if (!input_file)
00106     {
00107       message_out(ERROR, "ofx_proc_file():Unable to open the input file " + string(p_filename));
00108     }
00109 
00110     mkTempFileName("libofxtmpXXXXXX", tmp_filename, sizeof(tmp_filename));
00111 
00112     message_out(DEBUG, "ofx_proc_file(): Creating temp file: " + string(tmp_filename));
00113     tmp_file_fd = mkstemp(tmp_filename);
00114     if (tmp_file_fd)
00115     {
00116       tmp_file.open(tmp_filename);
00117       if (!tmp_file)
00118       {
00119         message_out(ERROR, "ofx_proc_file():Unable to open the created temp file " + string(tmp_filename));
00120         return -1;
00121       }
00122     }
00123     else
00124     {
00125       message_out(ERROR, "ofx_proc_file():Unable to create a temp file at " + string(tmp_filename));
00126       return -1;
00127     }
00128 
00129     if (input_file && tmp_file)
00130     {
00131       int header_separator_idx;
00132       string header_name;
00133       string header_value;
00134       string ofx_encoding;
00135       string ofx_charset;
00136       do
00137       {
00138         input_file.getline(buffer, sizeof(buffer), '\n');
00139         //cout<<buffer<<"\n";
00140         s_buffer.assign(buffer);
00141         //cout<<"input_file.gcount(): "<<input_file.gcount()<<" sizeof(buffer): "<<sizeof(buffer)<<endl;
00142         if (input_file.gcount() < (sizeof(buffer) - 1))
00143         {
00144           s_buffer.append("\n");
00145         }
00146         else if ( !input_file.eof() && input_file.fail())
00147         {
00148           input_file.clear();
00149         }
00150         int ofx_start_idx;
00151         if (ofx_start == false &&
00152             (
00153               (libofx_context->currentFileType() == OFX &&
00154                ((ofx_start_idx = s_buffer.find("<OFX>")) !=
00155                 string::npos || (ofx_start_idx = s_buffer.find("<ofx>")) != string::npos))
00156               || (libofx_context->currentFileType() == OFC &&
00157                   ((ofx_start_idx = s_buffer.find("<OFC>")) != string::npos ||
00158                    (ofx_start_idx = s_buffer.find("<ofc>")) != string::npos))
00159             )
00160            )
00161         {
00162           ofx_start = true;
00163           s_buffer.erase(0, ofx_start_idx); //Fix for really broken files that don't have a newline after the header.
00164           message_out(DEBUG, "ofx_proc_file():<OFX> or <OFC> has been found");
00165 #ifdef HAVE_ICONV
00166           string fromcode;
00167           string tocode;
00168           if (ofx_encoding.compare("USASCII") == 0)
00169           {
00170             if (ofx_charset.compare("ISO-8859-1") == 0 || ofx_charset.compare("8859-1") == 0)
00171             {
00172               //Only "ISO-8859-1" is actually a legal value, but since the banks follows the spec SO well...
00173               fromcode = "ISO-8859-1";
00174             }
00175             else if (ofx_charset.compare("1252") == 0 || ofx_charset.compare("CP1252") == 0)
00176             {
00177               //Only "1252" is actually a legal value, but since the banks follows the spec SO well...
00178               fromcode = "CP1252";
00179             }
00180             else if (ofx_charset.compare("NONE") == 0)
00181             {
00182               fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00183             }
00184             else
00185             {
00186               fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00187             }
00188           }
00189           else if (ofx_encoding.compare("UTF-8") == 0 || ofx_encoding.compare("UNICODE") == 0)
00190           {
00191                 //While "UNICODE" isn't a legal value, some cyrilic files do specify it as such...
00192             fromcode = "UTF-8";
00193           }
00194           else
00195           {
00196             fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00197           }
00198           tocode = LIBOFX_DEFAULT_OUTPUT_ENCODING;
00199           message_out(DEBUG, "ofx_proc_file(): Setting up iconv for fromcode: " + fromcode + ", tocode: " + tocode);
00200           conversion_descriptor = iconv_open (tocode.c_str(), fromcode.c_str());
00201 #endif
00202         }
00203         else
00204         {
00205           //We are still in the headers
00206           if ((header_separator_idx = s_buffer.find(':')) != string::npos)
00207           {
00208             //Header processing
00209             header_name.assign(s_buffer.substr(0, header_separator_idx));
00210             header_value.assign(s_buffer.substr(header_separator_idx + 1));
00211             while ( header_value[header_value.length() -1 ] == '\n' ||
00212                     header_value[header_value.length() -1 ] == '\r' )
00213               header_value.erase(header_value.length() - 1);
00214             message_out(DEBUG, "ofx_proc_file():Header: " + header_name + " with value: " + header_value + " has been found");
00215             if (header_name.compare("ENCODING") == 0)
00216             {
00217               ofx_encoding.assign(header_value);
00218             }
00219             if (header_name.compare("CHARSET") == 0)
00220             {
00221               ofx_charset.assign(header_value);
00222             }
00223           }
00224         }
00225 
00226         if (ofx_start == true && ofx_end == false)
00227         {
00228           s_buffer = sanitize_proprietary_tags(s_buffer);
00229           //cout<< s_buffer<<"\n";
00230 #ifdef HAVE_ICONV
00231           memset(iconv_buffer, 0, READ_BUFFER_SIZE * 2);
00232           size_t inbytesleft = strlen(s_buffer.c_str());
00233           size_t outbytesleft = READ_BUFFER_SIZE * 2 - 1;
00234 #ifdef OS_WIN32
00235           const char * inchar = (const char *)s_buffer.c_str();
00236 #else
00237           char * inchar = (char *)s_buffer.c_str();
00238 #endif
00239           char * outchar = iconv_buffer;
00240           int iconv_retval = iconv (conversion_descriptor,
00241                                     &inchar, &inbytesleft,
00242                                     &outchar, &outbytesleft);
00243           if (iconv_retval == -1)
00244           {
00245             message_out(ERROR, "ofx_proc_file(): Conversion error");
00246           }
00247           s_buffer = iconv_buffer;
00248 #endif
00249           tmp_file.write(s_buffer.c_str(), s_buffer.length());
00250         }
00251 
00252         if (ofx_start == true &&
00253             (
00254               (libofx_context->currentFileType() == OFX &&
00255                ((ofx_start_idx = s_buffer.find("</OFX>")) != string::npos ||
00256                 (ofx_start_idx = s_buffer.find("</ofx>")) != string::npos))
00257               || (libofx_context->currentFileType() == OFC &&
00258                   ((ofx_start_idx = s_buffer.find("</OFC>")) != string::npos ||
00259                    (ofx_start_idx = s_buffer.find("</ofc>")) != string::npos))
00260             )
00261            )
00262         {
00263           ofx_end = true;
00264           message_out(DEBUG, "ofx_proc_file():</OFX> or </OFC>  has been found");
00265         }
00266 
00267       }
00268       while (!input_file.eof() && !input_file.bad());
00269     }
00270     input_file.close();
00271     tmp_file.close();
00272 #ifdef HAVE_ICONV
00273     iconv_close(conversion_descriptor);
00274 #endif
00275     char filename_openspdtd[255];
00276     char filename_dtd[255];
00277     char filename_ofx[255];
00278     strncpy(filename_openspdtd, find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255); //The opensp sgml dtd file
00279     if (libofx_context->currentFileType() == OFX)
00280     {
00281       strncpy(filename_dtd, find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255); //The ofx dtd file
00282     }
00283     else if (libofx_context->currentFileType() == OFC)
00284     {
00285       strncpy(filename_dtd, find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255); //The ofc dtd file
00286     }
00287     else
00288     {
00289       message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00290     }
00291 
00292     if ((string)filename_dtd != "" && (string)filename_openspdtd != "")
00293     {
00294       strncpy(filename_ofx, tmp_filename, 255); //The processed ofx file
00295       filenames[0] = filename_openspdtd;
00296       filenames[1] = filename_dtd;
00297       filenames[2] = filename_ofx;
00298       if (libofx_context->currentFileType() == OFX)
00299       {
00300         ofx_proc_sgml(libofx_context, 3, filenames);
00301       }
00302       else if (libofx_context->currentFileType() == OFC)
00303       {
00304         ofc_proc_sgml(libofx_context, 3, filenames);
00305       }
00306       else
00307       {
00308         message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00309       }
00310       if (remove(tmp_filename) != 0)
00311       {
00312         message_out(ERROR, "ofx_proc_file(): Error deleting temporary file " + string(tmp_filename));
00313       }
00314     }
00315     else
00316     {
00317       message_out(ERROR, "ofx_proc_file(): FATAL: Missing DTD, aborting");
00318     }
00319   }
00320   else
00321   {
00322     message_out(ERROR, "ofx_proc_file():No input file specified");
00323   }
00324   return 0;
00325 }
00326 
00327 
00328 
00329 int libofx_proc_buffer(LibofxContextPtr ctx,
00330                        const char *s, unsigned int size)
00331 {
00332   ofstream tmp_file;
00333   string s_buffer;
00334   char *filenames[3];
00335   char tmp_filename[256];
00336   int tmp_file_fd;
00337   ssize_t pos;
00338   LibofxContext *libofx_context;
00339 
00340   libofx_context = (LibofxContext*)ctx;
00341 
00342   if (size == 0)
00343   {
00344     message_out(ERROR,
00345                 "ofx_proc_file(): bad size");
00346     return -1;
00347   }
00348   s_buffer = string(s, size);
00349 
00350   mkTempFileName("libofxtmpXXXXXX", tmp_filename, sizeof(tmp_filename));
00351   message_out(DEBUG, "ofx_proc_file(): Creating temp file: " + string(tmp_filename));
00352   tmp_file_fd = mkstemp(tmp_filename);
00353   if (tmp_file_fd)
00354   {
00355     tmp_file.open(tmp_filename);
00356     if (!tmp_file)
00357     {
00358       message_out(ERROR, "ofx_proc_file():Unable to open the created output file " + string(tmp_filename));
00359       return -1;
00360     }
00361   }
00362   else
00363   {
00364     message_out(ERROR, "ofx_proc_file():Unable to create a temp file at " + string(tmp_filename));
00365     return -1;
00366   }
00367 
00368   if (libofx_context->currentFileType() == OFX)
00369   {
00370     pos = s_buffer.find("<OFX>");
00371     if (pos == string::npos)
00372       pos = s_buffer.find("<ofx>");
00373   }
00374   else if (libofx_context->currentFileType() == OFC)
00375   {
00376     pos = s_buffer.find("<OFC>");
00377     if (pos == string::npos)
00378       pos = s_buffer.find("<ofc>");
00379   }
00380   else
00381   {
00382     message_out(ERROR, "ofx_proc(): unknown file type");
00383     return -1;
00384   }
00385   if (pos == string::npos || pos > s_buffer.size())
00386   {
00387     message_out(ERROR, "ofx_proc():<OFX> has not been found");
00388     return -1;
00389   }
00390   else
00391   {
00392     // erase everything before the OFX tag
00393     s_buffer.erase(0, pos);
00394     message_out(DEBUG, "ofx_proc_file():<OF?> has been found");
00395   }
00396 
00397   if (libofx_context->currentFileType() == OFX)
00398   {
00399     pos = s_buffer.find("</OFX>");
00400     if (pos == string::npos)
00401       pos = s_buffer.find("</ofx>");
00402   }
00403   else if (libofx_context->currentFileType() == OFC)
00404   {
00405     pos = s_buffer.find("</OFC>");
00406     if (pos == string::npos)
00407       pos = s_buffer.find("</ofc>");
00408   }
00409   else
00410   {
00411     message_out(ERROR, "ofx_proc(): unknown file type");
00412     return -1;
00413   }
00414 
00415   if (pos == string::npos || pos > s_buffer.size())
00416   {
00417     message_out(ERROR, "ofx_proc():</OF?> has not been found");
00418     return -1;
00419   }
00420   else
00421   {
00422     // erase everything after the /OFX tag
00423     if (s_buffer.size() > pos + 6)
00424       s_buffer.erase(pos + 6);
00425     message_out(DEBUG, "ofx_proc_file():<OFX> has been found");
00426   }
00427 
00428   s_buffer = sanitize_proprietary_tags(s_buffer);
00429   tmp_file.write(s_buffer.c_str(), s_buffer.length());
00430 
00431   tmp_file.close();
00432 
00433   char filename_openspdtd[255];
00434   char filename_dtd[255];
00435   char filename_ofx[255];
00436   strncpy(filename_openspdtd, find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255); //The opensp sgml dtd file
00437   if (libofx_context->currentFileType() == OFX)
00438   {
00439     strncpy(filename_dtd, find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255); //The ofx dtd file
00440   }
00441   else if (libofx_context->currentFileType() == OFC)
00442   {
00443     strncpy(filename_dtd, find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255); //The ofc dtd file
00444   }
00445   else
00446   {
00447     message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00448   }
00449 
00450   if ((string)filename_dtd != "" && (string)filename_openspdtd != "")
00451   {
00452     strncpy(filename_ofx, tmp_filename, 255); //The processed ofx file
00453     filenames[0] = filename_openspdtd;
00454     filenames[1] = filename_dtd;
00455     filenames[2] = filename_ofx;
00456     if (libofx_context->currentFileType() == OFX)
00457     {
00458       ofx_proc_sgml(libofx_context, 3, filenames);
00459     }
00460     else if (libofx_context->currentFileType() == OFC)
00461     {
00462       ofc_proc_sgml(libofx_context, 3, filenames);
00463     }
00464     else
00465     {
00466       message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00467     }
00468     if (remove(tmp_filename) != 0)
00469     {
00470       message_out(ERROR, "ofx_proc_file(): Error deleting temporary file " + string(tmp_filename));
00471     }
00472   }
00473   else
00474   {
00475     message_out(ERROR, "ofx_proc_file(): FATAL: Missing DTD, aborting");
00476   }
00477 
00478   return 0;
00479 }
00480 
00481 
00482 
00483 
00484 
00485 
00490 string sanitize_proprietary_tags(string input_string)
00491 {
00492   unsigned int i;
00493   size_t input_string_size;
00494   bool strip = false;
00495   bool tag_open = false;
00496   int tag_open_idx = 0; //Are we within < > ?
00497   bool closing_tag_open = false; //Are we within </ > ?
00498   int orig_tag_open_idx = 0;
00499   bool proprietary_tag = false; //Are we within a proprietary element?
00500   bool proprietary_closing_tag = false;
00501   int crop_end_idx = 0;
00502   char buffer[READ_BUFFER_SIZE] = "";
00503   char tagname[READ_BUFFER_SIZE] = "";
00504   int tagname_idx = 0;
00505   char close_tagname[READ_BUFFER_SIZE] = "";
00506 
00507   for (i = 0; i < READ_BUFFER_SIZE; i++)
00508   {
00509     buffer[i] = 0;
00510     tagname[i] = 0;
00511     close_tagname[i] = 0;
00512   }
00513 
00514   input_string_size = input_string.size();
00515 
00516   for (i = 0; i <= input_string_size; i++)
00517   {
00518     if (input_string.c_str()[i] == '<')
00519     {
00520       tag_open = true;
00521       tag_open_idx = i;
00522       if (proprietary_tag == true && input_string.c_str()[i+1] == '/')
00523       {
00524         //We are now in a closing tag
00525         closing_tag_open = true;
00526         //cout<<"Comparaison: "<<tagname<<"|"<<&(input_string.c_str()[i+2])<<"|"<<strlen(tagname)<<endl;
00527         if (strncmp(tagname, &(input_string.c_str()[i+2]), strlen(tagname)) != 0)
00528         {
00529           //If it is the begining of an other tag
00530           //cout<<"DIFFERENT!"<<endl;
00531           crop_end_idx = i - 1;
00532           strip = true;
00533         }
00534         else
00535         {
00536           //Otherwise, it is the start of the closing tag of the proprietary tag
00537           proprietary_closing_tag = true;
00538         }
00539       }
00540       else if (proprietary_tag == true)
00541       {
00542         //It is the start of a new tag, following a proprietary tag
00543         crop_end_idx = i - 1;
00544         strip = true;
00545       }
00546     }
00547     else if (input_string.c_str()[i] == '>')
00548     {
00549       tag_open = false;
00550       closing_tag_open = false;
00551       tagname[tagname_idx] = 0;
00552       tagname_idx = 0;
00553       if (proprietary_closing_tag == true)
00554       {
00555         crop_end_idx = i;
00556         strip = true;
00557       }
00558     }
00559     else if (tag_open == true && closing_tag_open == false)
00560     {
00561       if (input_string.c_str()[i] == '.')
00562       {
00563         if (proprietary_tag != true)
00564         {
00565           orig_tag_open_idx = tag_open_idx;
00566           proprietary_tag = true;
00567         }
00568       }
00569       tagname[tagname_idx] = input_string.c_str()[i];
00570       tagname_idx++;
00571     }
00572     //cerr <<i<<endl;
00573     if (strip == true && orig_tag_open_idx < input_string.size())
00574     {
00575       input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
00576       message_out(INFO, "sanitize_proprietary_tags() (end tag or new tag) removed: " + string(buffer));
00577       input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
00578       i = orig_tag_open_idx - 1;
00579       proprietary_tag = false;
00580       proprietary_closing_tag = false;
00581       closing_tag_open = false;
00582       tag_open = false;
00583       strip = false;
00584     }
00585 
00586   }//end for
00587   if (proprietary_tag == true && orig_tag_open_idx < input_string.size())
00588   {
00589     if (crop_end_idx == 0)   //no closing tag
00590     {
00591       crop_end_idx = input_string.size() - 1;
00592     }
00593     input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
00594     message_out(INFO, "sanitize_proprietary_tags() (end of line) removed: " + string(buffer));
00595     input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
00596   }
00597   return input_string;
00598 }
00599 
00600 
00601 #ifdef OS_WIN32
00602 static std::string get_dtd_installation_directory()
00603 {
00604   // Partial implementation of
00605   // http://developer.gnome.org/doc/API/2.0/glib/glib-Windows-Compatibility-Functions.html#g-win32-get-package-installation-directory
00606   char ch_fn[MAX_PATH], *p;
00607   std::string str_fn;
00608 
00609   if (!GetModuleFileName(NULL, ch_fn, MAX_PATH)) return "";
00610 
00611   if ((p = strrchr(ch_fn, '\\')) != NULL)
00612     * p = '\0';
00613 
00614   p = strrchr(ch_fn, '\\');
00615   if (p && (_stricmp(p + 1, "bin") == 0 ||
00616             _stricmp(p + 1, "lib") == 0))
00617     *p = '\0';
00618 
00619   str_fn = ch_fn;
00620   str_fn += "\\share\\libofx\\dtd";
00621 
00622   return str_fn;
00623 }
00624 #endif
00625 
00626 
00639 string find_dtd(LibofxContextPtr ctx, string dtd_filename)
00640 {
00641   string dtd_path_filename;
00642   char *env_dtd_path;
00643 
00644   dtd_path_filename = reinterpret_cast<const LibofxContext*>(ctx)->dtdDir();
00645   if (!dtd_path_filename.empty())
00646   {
00647     dtd_path_filename.append(dtd_filename);
00648     ifstream dtd_file(dtd_path_filename.c_str());
00649     if (dtd_file)
00650     {
00651       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00652       return dtd_path_filename;
00653     }
00654   }
00655 
00656 #ifdef OS_WIN32
00657   dtd_path_filename = get_dtd_installation_directory();
00658   if (!dtd_path_filename.empty())
00659   {
00660     dtd_path_filename.append(DIRSEP);
00661     dtd_path_filename.append(dtd_filename);
00662     ifstream dtd_file(dtd_path_filename.c_str());
00663     if (dtd_file)
00664     {
00665       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00666       return dtd_path_filename;
00667     }
00668   }
00669 #endif
00670   /* Search in environement variable OFX_DTD_PATH */
00671   env_dtd_path = getenv("OFX_DTD_PATH");
00672   if (env_dtd_path)
00673   {
00674     dtd_path_filename.append(env_dtd_path);
00675     dtd_path_filename.append(DIRSEP);
00676     dtd_path_filename.append(dtd_filename);
00677     ifstream dtd_file(dtd_path_filename.c_str());
00678     if (!dtd_file)
00679     {
00680       message_out(STATUS, "find_dtd():OFX_DTD_PATH env variable was was present, but unable to open the file " + dtd_path_filename);
00681     }
00682     else
00683     {
00684       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00685       return dtd_path_filename;
00686     }
00687   }
00688 
00689   for (int i = 0; i < DTD_SEARCH_PATH_NUM; i++)
00690   {
00691     dtd_path_filename = DTD_SEARCH_PATH[i];
00692     dtd_path_filename.append(DIRSEP);
00693     dtd_path_filename.append(dtd_filename);
00694     ifstream dtd_file(dtd_path_filename.c_str());
00695     if (!dtd_file)
00696     {
00697       message_out(DEBUG, "find_dtd():Unable to open the file " + dtd_path_filename);
00698     }
00699     else
00700     {
00701       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00702       return dtd_path_filename;
00703     }
00704   }
00705 
00706   /* Last resort, look in source tree relative path (useful for development) */
00707   dtd_path_filename = "";
00708   dtd_path_filename.append("..");
00709   dtd_path_filename.append(DIRSEP);
00710   dtd_path_filename.append("dtd");
00711   dtd_path_filename.append(DIRSEP);
00712   dtd_path_filename.append(dtd_filename);
00713   ifstream dtd_file(dtd_path_filename.c_str());
00714   if (!dtd_file)
00715   {
00716     message_out(DEBUG, "find_dtd(): Unable to open the file " + dtd_path_filename + ", most likely we are not in the source tree.");
00717   }
00718   else
00719   {
00720     message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00721     return dtd_path_filename;
00722   }
00723 
00724 
00725   message_out(ERROR, "find_dtd():Unable to find the DTD named " + dtd_filename);
00726   return "";
00727 }
00728 
00729