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               fromcode = "ISO-8859-1";
00173             }
00174             else if (ofx_charset.compare("1252") == 0)
00175             {
00176               fromcode = "CP1252";
00177             }
00178             else if (ofx_charset.compare("NONE") == 0)
00179             {
00180               fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00181             }
00182             else
00183             {
00184               fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00185             }
00186           }
00187           else if (ofx_encoding.compare("UTF-8") == 0)
00188           {
00189             fromcode = "UTF-8";
00190           }
00191           else
00192           {
00193             fromcode = LIBOFX_DEFAULT_INPUT_ENCODING;
00194           }
00195           tocode = LIBOFX_DEFAULT_OUTPUT_ENCODING;
00196           message_out(DEBUG, "ofx_proc_file(): Setting up iconv for fromcode: " + fromcode + ", tocode: " + tocode);
00197           conversion_descriptor = iconv_open (tocode.c_str(), fromcode.c_str());
00198 #endif
00199         }
00200         else
00201         {
00202           //We are still in the headers
00203           if ((header_separator_idx = s_buffer.find(':')) != string::npos)
00204           {
00205             //Header processing
00206             header_name.assign(s_buffer.substr(0, header_separator_idx));
00207             header_value.assign(s_buffer.substr(header_separator_idx + 1));
00208             while ( header_value[header_value.length() -1 ] == '\n' ||
00209                     header_value[header_value.length() -1 ] == '\r' )
00210               header_value.erase(header_value.length() - 1);
00211             message_out(DEBUG, "ofx_proc_file():Header: " + header_name + " with value: " + header_value + " has been found");
00212             if (header_name.compare("ENCODING") == 0)
00213             {
00214               ofx_encoding.assign(header_value);
00215             }
00216             if (header_name.compare("CHARSET") == 0)
00217             {
00218               ofx_charset.assign(header_value);
00219             }
00220           }
00221         }
00222 
00223         if (ofx_start == true && ofx_end == false)
00224         {
00225           s_buffer = sanitize_proprietary_tags(s_buffer);
00226           //cout<< s_buffer<<"\n";
00227 #ifdef HAVE_ICONV
00228           memset(iconv_buffer, 0, READ_BUFFER_SIZE * 2);
00229           size_t inbytesleft = strlen(s_buffer.c_str());
00230           size_t outbytesleft = READ_BUFFER_SIZE * 2 - 1;
00231 #ifdef OS_WIN32
00232           const char * inchar = (const char *)s_buffer.c_str();
00233 #else
00234           char * inchar = (char *)s_buffer.c_str();
00235 #endif
00236           char * outchar = iconv_buffer;
00237           int iconv_retval = iconv (conversion_descriptor,
00238                                     &inchar, &inbytesleft,
00239                                     &outchar, &outbytesleft);
00240           if (iconv_retval == -1)
00241           {
00242             message_out(ERROR, "ofx_proc_file(): Conversion error");
00243           }
00244           s_buffer = iconv_buffer;
00245 #endif
00246           tmp_file.write(s_buffer.c_str(), s_buffer.length());
00247         }
00248 
00249         if (ofx_start == true &&
00250             (
00251               (libofx_context->currentFileType() == OFX &&
00252                ((ofx_start_idx = s_buffer.find("</OFX>")) != string::npos ||
00253                 (ofx_start_idx = s_buffer.find("</ofx>")) != string::npos))
00254               || (libofx_context->currentFileType() == OFC &&
00255                   ((ofx_start_idx = s_buffer.find("</OFC>")) != string::npos ||
00256                    (ofx_start_idx = s_buffer.find("</ofc>")) != string::npos))
00257             )
00258            )
00259         {
00260           ofx_end = true;
00261           message_out(DEBUG, "ofx_proc_file():</OFX> or </OFC>  has been found");
00262         }
00263 
00264       }
00265       while (!input_file.eof() && !input_file.bad());
00266     }
00267     input_file.close();
00268     tmp_file.close();
00269 #ifdef HAVE_ICONV
00270     iconv_close(conversion_descriptor);
00271 #endif
00272     char filename_openspdtd[255];
00273     char filename_dtd[255];
00274     char filename_ofx[255];
00275     strncpy(filename_openspdtd, find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255); //The opensp sgml dtd file
00276     if (libofx_context->currentFileType() == OFX)
00277     {
00278       strncpy(filename_dtd, find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255); //The ofx dtd file
00279     }
00280     else if (libofx_context->currentFileType() == OFC)
00281     {
00282       strncpy(filename_dtd, find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255); //The ofc dtd file
00283     }
00284     else
00285     {
00286       message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00287     }
00288 
00289     if ((string)filename_dtd != "" && (string)filename_openspdtd != "")
00290     {
00291       strncpy(filename_ofx, tmp_filename, 255); //The processed ofx file
00292       filenames[0] = filename_openspdtd;
00293       filenames[1] = filename_dtd;
00294       filenames[2] = filename_ofx;
00295       if (libofx_context->currentFileType() == OFX)
00296       {
00297         ofx_proc_sgml(libofx_context, 3, filenames);
00298       }
00299       else if (libofx_context->currentFileType() == OFC)
00300       {
00301         ofc_proc_sgml(libofx_context, 3, filenames);
00302       }
00303       else
00304       {
00305         message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00306       }
00307       if (remove(tmp_filename) != 0)
00308       {
00309         message_out(ERROR, "ofx_proc_file(): Error deleting temporary file " + string(tmp_filename));
00310       }
00311     }
00312     else
00313     {
00314       message_out(ERROR, "ofx_proc_file(): FATAL: Missing DTD, aborting");
00315     }
00316   }
00317   else
00318   {
00319     message_out(ERROR, "ofx_proc_file():No input file specified");
00320   }
00321   return 0;
00322 }
00323 
00324 
00325 
00326 int libofx_proc_buffer(LibofxContextPtr ctx,
00327                        const char *s, unsigned int size)
00328 {
00329   ofstream tmp_file;
00330   string s_buffer;
00331   char *filenames[3];
00332   char tmp_filename[256];
00333   int tmp_file_fd;
00334   ssize_t pos;
00335   LibofxContext *libofx_context;
00336 
00337   libofx_context = (LibofxContext*)ctx;
00338 
00339   if (size == 0)
00340   {
00341     message_out(ERROR,
00342                 "ofx_proc_file(): bad size");
00343     return -1;
00344   }
00345   s_buffer = string(s, size);
00346 
00347   mkTempFileName("libofxtmpXXXXXX", tmp_filename, sizeof(tmp_filename));
00348   message_out(DEBUG, "ofx_proc_file(): Creating temp file: " + string(tmp_filename));
00349   tmp_file_fd = mkstemp(tmp_filename);
00350   if(tmp_file_fd)
00351   {
00352   tmp_file.open(tmp_filename);
00353   if (!tmp_file)
00354     {
00355       message_out(ERROR, "ofx_proc_file():Unable to open the created output file " + string(tmp_filename));
00356       return -1;
00357     }
00358   }
00359   else
00360   {
00361       message_out(ERROR, "ofx_proc_file():Unable to create a temp file at " + string(tmp_filename));
00362       return -1;
00363   }
00364 
00365   if (libofx_context->currentFileType() == OFX)
00366   {
00367     pos = s_buffer.find("<OFX>");
00368     if (pos == string::npos)
00369       pos = s_buffer.find("<ofx>");
00370   }
00371   else if (libofx_context->currentFileType() == OFC)
00372   {
00373     pos = s_buffer.find("<OFC>");
00374     if (pos == string::npos)
00375       pos = s_buffer.find("<ofc>");
00376   }
00377   else
00378   {
00379     message_out(ERROR, "ofx_proc(): unknown file type");
00380     return -1;
00381   }
00382   if (pos == string::npos || pos > s_buffer.size())
00383   {
00384     message_out(ERROR, "ofx_proc():<OFX> has not been found");
00385     return -1;
00386   }
00387   else
00388   {
00389     // erase everything before the OFX tag
00390     s_buffer.erase(0, pos);
00391     message_out(DEBUG, "ofx_proc_file():<OF?> has been found");
00392   }
00393 
00394   if (libofx_context->currentFileType() == OFX)
00395   {
00396     pos = s_buffer.find("</OFX>");
00397     if (pos == string::npos)
00398       pos = s_buffer.find("</ofx>");
00399   }
00400   else if (libofx_context->currentFileType() == OFC)
00401   {
00402     pos = s_buffer.find("</OFC>");
00403     if (pos == string::npos)
00404       pos = s_buffer.find("</ofc>");
00405   }
00406   else
00407   {
00408     message_out(ERROR, "ofx_proc(): unknown file type");
00409     return -1;
00410   }
00411 
00412   if (pos == string::npos || pos > s_buffer.size())
00413   {
00414     message_out(ERROR, "ofx_proc():</OF?> has not been found");
00415     return -1;
00416   }
00417   else
00418   {
00419     // erase everything after the /OFX tag
00420     if (s_buffer.size() > pos + 6)
00421       s_buffer.erase(pos + 6);
00422     message_out(DEBUG, "ofx_proc_file():<OFX> has been found");
00423   }
00424 
00425   s_buffer = sanitize_proprietary_tags(s_buffer);
00426   tmp_file.write(s_buffer.c_str(), s_buffer.length());
00427 
00428   tmp_file.close();
00429 
00430   char filename_openspdtd[255];
00431   char filename_dtd[255];
00432   char filename_ofx[255];
00433   strncpy(filename_openspdtd, find_dtd(ctx, OPENSPDCL_FILENAME).c_str(), 255); //The opensp sgml dtd file
00434   if (libofx_context->currentFileType() == OFX)
00435   {
00436     strncpy(filename_dtd, find_dtd(ctx, OFX160DTD_FILENAME).c_str(), 255); //The ofx dtd file
00437   }
00438   else if (libofx_context->currentFileType() == OFC)
00439   {
00440     strncpy(filename_dtd, find_dtd(ctx, OFCDTD_FILENAME).c_str(), 255); //The ofc dtd file
00441   }
00442   else
00443   {
00444     message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00445   }
00446 
00447   if ((string)filename_dtd != "" && (string)filename_openspdtd != "")
00448   {
00449     strncpy(filename_ofx, tmp_filename, 255); //The processed ofx file
00450     filenames[0] = filename_openspdtd;
00451     filenames[1] = filename_dtd;
00452     filenames[2] = filename_ofx;
00453     if (libofx_context->currentFileType() == OFX)
00454     {
00455       ofx_proc_sgml(libofx_context, 3, filenames);
00456     }
00457     else if (libofx_context->currentFileType() == OFC)
00458     {
00459       ofc_proc_sgml(libofx_context, 3, filenames);
00460     }
00461     else
00462     {
00463       message_out(ERROR, string("ofx_proc_file(): Error unknown file format for the OFX parser"));
00464     }
00465     if (remove(tmp_filename) != 0)
00466     {
00467       message_out(ERROR, "ofx_proc_file(): Error deleting temporary file " + string(tmp_filename));
00468     }
00469   }
00470   else
00471   {
00472     message_out(ERROR, "ofx_proc_file(): FATAL: Missing DTD, aborting");
00473   }
00474 
00475   return 0;
00476 }
00477 
00478 
00479 
00480 
00481 
00482 
00487 string sanitize_proprietary_tags(string input_string)
00488 {
00489   unsigned int i;
00490   size_t input_string_size;
00491   bool strip = false;
00492   bool tag_open = false;
00493   int tag_open_idx = 0; //Are we within < > ?
00494   bool closing_tag_open = false; //Are we within </ > ?
00495   int orig_tag_open_idx = 0;
00496   bool proprietary_tag = false; //Are we within a proprietary element?
00497   bool proprietary_closing_tag = false;
00498   int crop_end_idx = 0;
00499   char buffer[READ_BUFFER_SIZE] = "";
00500   char tagname[READ_BUFFER_SIZE] = "";
00501   int tagname_idx = 0;
00502   char close_tagname[READ_BUFFER_SIZE] = "";
00503 
00504   for (i = 0; i < READ_BUFFER_SIZE; i++)
00505   {
00506     buffer[i] = 0;
00507     tagname[i] = 0;
00508     close_tagname[i] = 0;
00509   }
00510 
00511   input_string_size = input_string.size();
00512 
00513   for (i = 0; i <= input_string_size; i++)
00514   {
00515     if (input_string.c_str()[i] == '<')
00516     {
00517       tag_open = true;
00518       tag_open_idx = i;
00519       if (proprietary_tag == true && input_string.c_str()[i+1] == '/')
00520       {
00521         //We are now in a closing tag
00522         closing_tag_open = true;
00523         //cout<<"Comparaison: "<<tagname<<"|"<<&(input_string.c_str()[i+2])<<"|"<<strlen(tagname)<<endl;
00524         if (strncmp(tagname, &(input_string.c_str()[i+2]), strlen(tagname)) != 0)
00525         {
00526           //If it is the begining of an other tag
00527           //cout<<"DIFFERENT!"<<endl;
00528           crop_end_idx = i - 1;
00529           strip = true;
00530         }
00531         else
00532         {
00533           //Otherwise, it is the start of the closing tag of the proprietary tag
00534           proprietary_closing_tag = true;
00535         }
00536       }
00537       else if (proprietary_tag == true)
00538       {
00539         //It is the start of a new tag, following a proprietary tag
00540         crop_end_idx = i - 1;
00541         strip = true;
00542       }
00543     }
00544     else if (input_string.c_str()[i] == '>')
00545     {
00546       tag_open = false;
00547       closing_tag_open = false;
00548       tagname[tagname_idx] = 0;
00549       tagname_idx = 0;
00550       if (proprietary_closing_tag == true)
00551       {
00552         crop_end_idx = i;
00553         strip = true;
00554       }
00555     }
00556     else if (tag_open == true && closing_tag_open == false)
00557     {
00558       if (input_string.c_str()[i] == '.')
00559       {
00560         if (proprietary_tag != true)
00561         {
00562           orig_tag_open_idx = tag_open_idx;
00563           proprietary_tag = true;
00564         }
00565       }
00566       tagname[tagname_idx] = input_string.c_str()[i];
00567       tagname_idx++;
00568     }
00569     //cerr <<i<<endl;
00570     if (strip == true && orig_tag_open_idx < input_string.size())
00571     {
00572       input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
00573       message_out(INFO, "sanitize_proprietary_tags() (end tag or new tag) removed: " + string(buffer));
00574       input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
00575       i = orig_tag_open_idx - 1;
00576       proprietary_tag = false;
00577       proprietary_closing_tag = false;
00578       closing_tag_open = false;
00579       tag_open = false;
00580       strip = false;
00581     }
00582 
00583   }//end for
00584   if (proprietary_tag == true && orig_tag_open_idx < input_string.size())
00585   {
00586     if (crop_end_idx == 0)   //no closing tag
00587     {
00588       crop_end_idx = input_string.size() - 1;
00589     }
00590     input_string.copy(buffer, (crop_end_idx - orig_tag_open_idx) + 1, orig_tag_open_idx);
00591     message_out(INFO, "sanitize_proprietary_tags() (end of line) removed: " + string(buffer));
00592     input_string.erase(orig_tag_open_idx, (crop_end_idx - orig_tag_open_idx) + 1);
00593   }
00594   return input_string;
00595 }
00596 
00597 
00598 #ifdef OS_WIN32
00599 static std::string get_dtd_installation_directory()
00600 {
00601   // Partial implementation of
00602   // http://developer.gnome.org/doc/API/2.0/glib/glib-Windows-Compatibility-Functions.html#g-win32-get-package-installation-directory
00603   char ch_fn[MAX_PATH], *p;
00604   std::string str_fn;
00605 
00606   if (!GetModuleFileName(NULL, ch_fn, MAX_PATH)) return "";
00607 
00608   if ((p = strrchr(ch_fn, '\\')) != NULL)
00609     * p = '\0';
00610 
00611   p = strrchr(ch_fn, '\\');
00612   if (p && (_stricmp(p + 1, "bin") == 0 ||
00613             _stricmp(p + 1, "lib") == 0))
00614     *p = '\0';
00615 
00616   str_fn = ch_fn;
00617   str_fn += "\\share\\libofx\\dtd";
00618 
00619   return str_fn;
00620 }
00621 #endif
00622 
00623 
00636 string find_dtd(LibofxContextPtr ctx, string dtd_filename)
00637 {
00638   string dtd_path_filename;
00639   char *env_dtd_path;
00640 
00641   dtd_path_filename = reinterpret_cast<const LibofxContext*>(ctx)->dtdDir();
00642   if (!dtd_path_filename.empty())
00643   {
00644     dtd_path_filename.append(dtd_filename);
00645     ifstream dtd_file(dtd_path_filename.c_str());
00646     if (dtd_file)
00647     {
00648       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00649       return dtd_path_filename;
00650     }
00651   }
00652 
00653 #ifdef OS_WIN32
00654   dtd_path_filename = get_dtd_installation_directory();
00655   if (!dtd_path_filename.empty())
00656   {
00657         dtd_path_filename.append(DIRSEP);
00658     dtd_path_filename.append(dtd_filename);
00659     ifstream dtd_file(dtd_path_filename.c_str());
00660     if (dtd_file)
00661     {
00662       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00663       return dtd_path_filename;
00664     }
00665   }
00666 #endif
00667   /* Search in environement variable OFX_DTD_PATH */
00668   env_dtd_path = getenv("OFX_DTD_PATH");
00669   if (env_dtd_path)
00670   {
00671     dtd_path_filename.append(env_dtd_path);
00672     dtd_path_filename.append(DIRSEP);
00673     dtd_path_filename.append(dtd_filename);
00674     ifstream dtd_file(dtd_path_filename.c_str());
00675     if (!dtd_file)
00676     {
00677       message_out(STATUS, "find_dtd():OFX_DTD_PATH env variable was was present, but unable to open the file " + dtd_path_filename);
00678     }
00679     else
00680     {
00681       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00682       return dtd_path_filename;
00683     }
00684   }
00685 
00686   for (int i = 0; i < DTD_SEARCH_PATH_NUM; i++)
00687   {
00688     dtd_path_filename = DTD_SEARCH_PATH[i];
00689     dtd_path_filename.append(DIRSEP);
00690     dtd_path_filename.append(dtd_filename);
00691     ifstream dtd_file(dtd_path_filename.c_str());
00692     if (!dtd_file)
00693     {
00694       message_out(DEBUG, "find_dtd():Unable to open the file " + dtd_path_filename);
00695     }
00696     else
00697     {
00698       message_out(STATUS, "find_dtd():DTD found: " + dtd_path_filename);
00699       return dtd_path_filename;
00700     }
00701   }
00702 
00703   message_out(ERROR, "find_dtd():Unable to find the DTD named " + dtd_filename);
00704   return "";
00705 }
00706 
00707