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